Rust学习入门--【15】Rust 所有权

news2024/11/17 9:27:58

系列文章目录

Rust 语言是一种高效、可靠的通用高级语言,效率可以媲美 C / C++ 。本系列文件记录博主自学Rust的过程。欢迎大家一同学习。

Rust学习入门–【1】引言
Rust学习入门–【2】Rust 开发环境配置
Rust学习入门–【3】Cargo介绍
Rust学习入门–【4】Rust 输出到命令行
Rust学习入门–【5】源代码文件结构简介
Rust学习入门–【6】Rust 基础语法
Rust学习入门–【7】Rust 数据类型
Rust学习入门–【8】复合类型
Rust学习入门–【9】Rust 函数
Rust学习入门–【10】Rust 条件语句
Rust学习入门–【11】Rust 运算符
Rust学习入门–【12】Rust 循环
Rust学习入门–【13】Rust 字符串(上)
Rust学习入门–【14】Rust 字符串(下)


文章目录

  • 系列文章目录
  • Rust 所有权
  • 1、所有权规则
  • 2、内存分类
    • 栈 stack
    • 堆 heap
  • 3、所有权的概念
  • 4、转让所有权
    • 4.1、把一个变量赋值给另一个变量
    • 4.1、把变量传递给函数作为参数
    • 4.3、函数中返回一个变量作为返回值
  • 5、所有权和基本(原始)数据类型
  • 注意


Rust 所有权

大多数的编程语言都有管理内存的功能:

  • C/C++ 语言主要通过手动方式管理内存,开发者需要手动申请和释放内存资源。

  • Java 语言编写的程序在虚拟机(JVM)中运行,JVM 具备自动回收内存资源的功能。但这种方式常常会降低运行时效率,所以 JVM 会尽可能少的回收资源,这样也会使程序占用较大的内存资源。

所有权对大多数开发者而言是一个新颖的概念,它是 Rust 语言为高效使用内存而设计的语法机制。所有权是为了让 Rust 在编译阶段更有效地分析内存资源的有用性以实现内存管理而诞生的概念。


1、所有权规则

所有权有以下三条规则:

  1. Rust 中的每个值都有一个变量,称为其所有者。
  2. 一次只能有一个所有者。
  3. 当所有者不在程序运行范围时,该值将被删除。

2、内存分类

编程语言把内存分为两大类:

  • 栈 stack
  • 堆 heap

这两种分类并没有对实际的内存做什么,只是把系统分给应用程序的内存标识为上面的两大类而已。

栈 stack

栈 stack 是一种 后进先出 容器。就像我们的存储罐子,后面放进去的只能先拿出来(后面放进去的会放在上面)。

栈 stack 上存储的元素大小必须是已知的,也就是说如果一个变量或数据要放到栈上,那么它的大小在编译是就必须是明确的。

Rust 语言中所有标量类型都可以存储到栈上,因为它们的大小都是固定的。

而对于字符串这种复合类型,它们在运行时才会赋值,在编译时的大小是未知的。它们不能存储在栈上,而只能存储在 堆 上

堆 heap

堆 heap 用于存储那些在编译时大小未知的数据,也就是那些只有在运行时才能确定大小的数据。

我们一般在堆 heap 上存储那些动态类型的数据。一般在堆上存储那些可能在程序的整个生命周期中发生变化的数据。

是不受系统管理的,由用户自己管理,使用不当,内存溢出的可能性就大大增加了。

3、所有权的概念

所有权就是一个东西属不属于你,你有没有权力处理它,如:修改和删除。

Rust 语言中每一值都有一个对应的变量,这个变量就成为这个值的 所有者。从某些方面说,定义一个变量就是为这个变量和它存储的数据定义一种所有者管理,声明这个值由这个变量所有。

任何东西只有一个所有者,Rust 中是不允许有共同所有者这个概念的。

  • Rust 中,任何特定时刻,一个数据只能有一个所有者。

  • Rust 中,不允许两个变量同时指向同一块内存区域。变量必须指向不同的内存区域。

4、转让所有权

Rust 语言中转让所有权的方式有以下几种:

  • 把一个变量赋值给另一个变量。

  • 把变量传递给函数作为参数。

  • 函数中返回一个变量作为返回值。

4.1、把一个变量赋值给另一个变量

为了实现内存安全,Rust 严格控制谁可以使用内存和什么时候应该限制使用内存。

fn main(){

   // 向量 v 拥有堆上数据的所有权
   // 每次只能有一个变量对堆上的数据拥有所有权
   let v = vec![1,2,3]; 

   // 赋值会导致两个变量都对同一个数据拥有所有权
   // 因为两个变量指向了相同的内存块
   let v2 = v; 

   // Rust 会检查两个变量是否同时拥有堆上内存块的所有权。
   // 如果发生所有权竞争,它会自动将所有权判给给新的变量
   // 运行出错,因为 v 不再拥有数据的所有权
   println!("{:?}",v);
}

上面的代码中我们首先声明了一个向量 v。所有权的概念是只有一个变量绑定到资源,v 绑定到资源或 v2 绑定到资源。

赋值操作 ( v2 = v )会将资源的所有权转移到了 v2,移动后 v 就会变得无效。
在这里插入图片描述

4.1、把变量传递给函数作为参数

将堆中的对象传递给闭包或函数时,值的所有权也会发生变更

fn main(){
   let v = vec![1,2,3];     // 向量 v 拥有堆上数据的所有权
   let v2 = v;              // 向量 v 将所有权转让给 v2
   display(v2);             // v2 将所有权转让给函数参数 v3 ,v2 将变得不可用
   println!("In main {:?}",v2);    // v2 变得不可用
}
fn display(v3:Vec<i32>){
   println!("inside display {:?}",v3);
}

在这里插入图片描述

4.3、函数中返回一个变量作为返回值

传递给函数的所有权将在函数执行完成时失效。

即函数的形参获得的所有权将在离开函数后就失效了。

为了解决所有权失效的问题,我们可以让函数将拥有的对象返回给调用者。

fn main(){
   let v = vec![1,2,3];       // 向量 v 拥有堆上数据的所有权
   let v2 = v;                // 向量 v 将所有权转让给 v2
   let v2_return = display(v2);    
   println!("In main {:?}",v2_return);
}

fn display(v3:Vec<i32>)-> Vec<i32> { 
   // 返回同一个向量
   println!("inside display {:?}",v3);
   return v3;
}

编译运行上面的 Rust 代码,输出结果如下
在这里插入图片描述

5、所有权和基本(原始)数据类型

对于所有的基本数据类型,把一个变量赋值给另一个变量,并不是所有权转让,而是把数据复制给另一个对象。
也就是在内存上重新开辟一个区域,存储复制来的数据,然后把新的变量指向它。

这样做的原因,是因为原始数据类型并不需要占用那么大的内存。

fn main(){
   let num1 = 10;
   let num2 = num1;  // num1 只是将数据拷贝给 num2

   println!("num1 = {}",num1);
}

运行结果:
u1 = 10

注意

  1. 所有权只会发生堆上分配的数据,对比 C++,可以说所有权只会发生在指针上。
  2. 基本类型的存储都在栈上,因此没有所有权的概念。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/354640.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Maven的安装和配置

Maven的安装 1.1Maven是什么&#xff1f; 是阿帕奇的&#xff0c;就是代替原先手动导入jar包的方式 1.官方介绍 视频&#xff1a;百度百科-验证Maven是一款服务于Java平台的自动化构建工具。Maven 作为 Java 项目管理工具&#xff0c;它不仅可以用作包管理&#xff0c;还有许多…

DIDL4_前向传播与反向传播(模型参数的更新)

前向传播与反向传播前向传播与反向传播的作用前向传播及公式前向传播范例反向传播及公式反向传播范例小结前向传播计算图前向传播与反向传播的作用 在训练神经网络时&#xff0c;前向传播和反向传播相互依赖。 对于前向传播&#xff0c;我们沿着依赖的方向遍历计算图并计算其路…

# AutoSar一文概览

1.什么是AutoSar ​ AUTOSAR全称为“AUTomotive Open System ARchitecture”&#xff0c;译为“汽车开放系统体系结构”&#xff1b;AUTOSAR是由 全球各大汽车整车厂、汽车零部件供应商、汽车电子软件系统公司联合建立的一套标准协议、软件架构。 2.为什么汽车行业要定义一个…

DIDL5_数值稳定性和模型初始化

数值稳定性和模型初始化数值稳定性梯度不稳定的影响推导什么是梯度消失&#xff1f;什么是梯度爆炸&#xff1f;如何解决数值不稳定问题&#xff1f;——参数初始化参数初始化的几种方法默认初始化Xavier初始化小结当神经网络变得很深的时候&#xff0c;数值特别容易不稳定。我…

面试题67. 把字符串转换成整数

题目 写一个函数 StrToInt&#xff0c;实现把字符串转换成整数这个功能。不能使用 atoi 或者其他类似的库函数。 首先&#xff0c;该函数会根据需要丢弃无用的开头空格字符&#xff0c;直到寻找到第一个非空格的字符为止。 当我们寻找到的第一个非空字符为正或者负号时&#xf…

密度峰值聚类算法(DPC)

密度峰值聚类算法目录DPC算法1.1 DPC算法的两个假设1.2 DPC算法的两个重要概念1.3 DPC算法的执行步骤1.4 DPC算法的优缺点matlab代码密度计算函数计算delta寻找聚类中心点聚类算法目录 DPC算法 1.1 DPC算法的两个假设 1&#xff09;类簇中心被类簇中其他密度较低的数据点包围…

kubernetes 教程

K8s 安装kubectl 下载kubectl curl -LO "https://dl.k8s.io/release/**$(**curl -L -s https://dl.k8s.io/release/stable.txt**)**/bin/linux/amd64/kubectl" 安装 sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl 验证 kubectl versi…

学习 Python 之 Pygame 开发坦克大战(二)

学习 Python 之 Pygame 开发坦克大战&#xff08;二&#xff09;坦克大战的需求开始编写坦克大战1. 搭建主类框架2. 获取窗口中的事件3. 创建基类4. 初始化我方坦克类5. 完善我方坦克的移动5. 完善我方坦克的显示6. 在主类中加入我方坦克并完成坦克移动7. 初始化子弹类8. 完善子…

(考研湖科大教书匠计算机网络)第五章传输层-第一、二节:传输层概述及端口号、复用分用等概念

获取pdf&#xff1a;密码7281专栏目录首页&#xff1a;【专栏必读】考研湖科大教书匠计算机网络笔记导航 文章目录一&#xff1a;传输层概述&#xff08;1&#xff09;概述&#xff08;2&#xff09;从计算机网络体系结构角度看传输层&#xff08;3&#xff09;传输层意义二&am…

MySQL行转列列转行实例解析

文档准备要求&#xff1a;找出所有的用户没有安装的软件。创建两个表&#xff0c;用户表app_install 和 app表app建表语句&#xff1a;# 创建app表&#xff0c;并插入数据 create table app(id int,app varchar(32)); insert into app(id,app) values (1,微信),(2,QQ),(3,支付宝…

二叉树理论基础知识点

二叉树的种类 在我们解题过程中二叉树有两种主要的形式&#xff1a;满二叉树和完全二叉树 满二叉树 满二叉树&#xff1a;如果一棵二叉树只有度为0的结点和度为2的结点&#xff0c;并且度为0的结点在同一层上&#xff0c;则这棵二叉树为满二叉树。 如图所示&#xff1a; 这…

About Oracle Database Performance Method

bottleneck&#xff08;瓶颈&#xff09;&#xff1a; a point where resource contention is highest throughput(吞吐量)&#xff1a; the amount of work that can be completed in a specified time. response time (响应时间)&#xff1a; the time to complete a spec…

Java 日志简介

目录1、Slf4j2、Log4j3、LogBack4、Logback 优点5、ELK1、Slf4j slf4j 的全称是 Simple Loging Facade For Java&#xff0c;即它仅仅是一个为 Java 程序提供日志输出的统一接口&#xff0c;并不是一个具体的日志实现方案&#xff0c;就比如 JDBC 一样&#xff0c;只是一种规则…

解决:eclipse绿化版Resource注解报Resource cannot be resolved to a type问题

如图&#xff1a; 网上解决教程很多&#xff0c;我的eclipse是绿化版的&#xff0c;不需要安装 解决办法如下&#xff1a; 1、在eclipse中&#xff0c;进入到Window->Preferences->Java->Installed JREs中 默认显示如下&#xff1a; 2、点击Add-->Standard VM--…

分页插件

引入依赖 注意需要和SpringBoot的版本对应&#xff0c;否则分页可能不生效 使用的分页依赖&#xff1a; <!-- pagehelper 插件--><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</arti…

Dockerfile详解及优化技巧

写在前面 Dockerfile的默认相对路径是Dockerfile所在的目录&#xff1b;Dockerfile中的每一行会被视为一层镜像 一、Dockerfile 原理 1.1 镜像定义 首先我们先来回顾一下 Docker 镜像&#xff0c;它由多个只读层堆叠到一起&#xff0c;每一层是上一层的增量修改。基于镜像创…

深度学习炼丹-数据标准化

前言 一般机器学习任务其工作流程可总结为如下所示 pipeline。 在工业界,数据预处理步骤对模型精度的提高的发挥着重要作用。对于机器学习任务来说,广泛的数据预处理一般有四个阶段(视觉任务一般只需 Data Transformation): 数据清洗(Data Cleaning)、数据整合(Data Integ…

【c语言进阶】深度剖析整形数据

&#x1f680;write in front&#x1f680; &#x1f4dc;所属专栏&#xff1a; &#x1f6f0;️博客主页&#xff1a;睿睿的博客主页 &#x1f6f0;️代码仓库&#xff1a;&#x1f389;VS2022_C语言仓库 &#x1f3a1;您的点赞、关注、收藏、评论&#xff0c;是对我最大的激励…

C++010-C++嵌套循环

文章目录C010-C嵌套循环嵌套循环嵌套循环举例题目描述 输出1的个数题目描述 输出n行99乘法表题目描述 求s1!2!...10!作业在线练习&#xff1a;总结C010-C嵌套循环 在线练习&#xff1a; http://noi.openjudge.cn/ https://www.luogu.com.cn/ 嵌套循环 循环可以指挥计算机重复去…

自命为缓存之王的Caffeine(6)

您好&#xff0c;我是湘王&#xff0c;这是我的CSDN博客&#xff0c;欢迎您来&#xff0c;欢迎您再来&#xff5e;之前用Caffeine替代Redis的时候&#xff0c;发现先保存KV&#xff0c;再获取key&#xff0c;过期时间为3秒。但即使过了3秒&#xff0c;还是能获取到保存的数据。…