rust所有权
一、堆和栈
栈和堆都是程序运行时使用的内存,但是它们的结构不同。
1.栈
栈,英文是stack。是内存的一段区域。
栈是后进先出形式的。就像薯片桶,先放进去的一片只能后拿出来。
栈上存储的数据大小必须是已知且固定的。也就是说如果一个变量或数据要放到栈上,那么它的大小在编译是就必须是明确的。
例如,类型为i32的变量,它的大小是固定4个字节。
2.堆
堆,英文是heap。是内存的另一段区域。堆内存也叫做资源。
堆是缺乏组织的:当向堆放入数据时,你要请求一定大小的空间。内存分配器在堆的某处找到一块足够大的空位,把它标记为已使用,并返回一个表示该位置地址的指针。这个过程称作在堆上分配内存。因为指针大小是已知且固定的,所以可以将该指针存储在栈上,不过当需要实际数据时,必须去指针指向的内存读取数据。就像一个围棋棋盘,你可以把一枚棋子放到任意可以放得下的位置。
在编译时大小未知或大小可能变化的数据,要存储在堆上。
堆不受系统管理,由用户自己管理,因此,使用不当,内存溢出的可能性就大大增加了。
Rust与其他语言的区别
(1)指针超出作用域会自动释放堆内存:
对于简单类型的栈内存(如int)超出作用域后自动释放,这个功能各个语言都有。而对于new出来的堆内存,在c/c++中要手动释放,在java中要委托垃圾回收释放。而垃圾回收不是实时的,会影响性能,手动释放又总会有人忘记释放。而Rust对栈内存和堆内存一视同仁,超出作用域一律自动释放,相当于自动delete指针。所以rust避免了内存泄漏。
在作用域结束时释放资源的模式称作资源获取即初始化(Resource Acquisition Is Initialization (RAII))。
rust强制使用raii,所以任何对象在离开作用域时,它的析构函数就被调用,然后它占有的资源就被释放。
这避免了资源泄漏,所以你再也不用手动释放内存或者担心内存泄漏。
(2)所有权:
某段内存只能被最后的变量名所有,前面声明过的变量都作废,这样一段内存就只有一个所有者,只有所有者可以释放这块内存。这有效避免了被多个变量释放的问题,而且该操作是在编译期的,这可在编译期就能避免空指针问题。比如c++中,a和b指向同一块内存,如果delete a之后,再delete b就会出错,而rust中不会出现这种问题。
二、所有权
(一)所有权是什么
所有权是指对内存资源的控制权和管理权。
在Rust中,每个值都有一个唯一的所有者。定义一个变量就是声明这个值由这个变量所有。所有的值最终都要存储在一块内存上,变量拥有这个值其实是拥有这块内存。栈内存所有者就是声明时的变量,而堆内存所有者是分配返回的指针。
只有所有者才能释放这块内存,其他人不能释放这块内存。
当所有者超出作用域时,会自动释放这块内存。
所有权的规则:
1.Rust中的每一个值都有一个所有者。
2.值在任一时刻有且只有一个所有者。
3.当所有者离开作用域,这个值将被丢弃。
比如,
现在可以把Box当成一个指针,后面章节再讲解Box用法。
fn create_box() {let _box1 = Box::new(3i32);// 在堆上分配一个整型数据// `_box1` 在这里被销毁,内存得到释放。如果是c++,就得手动delete,否则就会内存泄漏。这就是区别。
}
fn main() {let _box2 = Box::new(5i32);// 在堆上分配一个整型数据// 嵌套作用域:{let _box3 = Box::new(4i32);// 在堆上分配一个整型数据// `_box3` 在这里被销毁,内存得到释放}// 创建一大堆 box 完全不需要手动释放内存!for _ in 0u32..1000 {create_box();}// `_box2` 在这里被销毁,内存得到释放
}
(二)转让所有权
所有权可以转让。转让所有权也叫move。
就是由新变量拥有内存,旧变量变成无效的。
s1转让给s2,就像下图所示。s2拥有堆内存,s1变无效。

Rust语言中转让所有权的方式有以下几种:
1.把一个变量赋值给另一个变量。
2.把变量值传递给函数作为参数。
3.函数中返回一个变量作为返回值。
1.把一个变量赋值给另一个变量
fn main(){let a = Box::new(5i32);// a 是一个指向堆分配的整数的指针let b = a;// 移动a到b,把a的指针地址(而非数据)复制到b。现在是b拥有堆内存,a变无效。//println!("a contains: {}", a);// 报错!a无效,因为它不再拥有那部分堆上的内存。
}
2.把变量值传递给函数作为参数。
值传递方式,值的所有权也会发生变更
fn destroy_box(c: Box<i32>) {println!("Destroying a box that contains {}", c);// c 被销毁且内存得到释放
}
fn main() {let a = Box::new(5i32);// a 是一个指向堆分配的整数的指针destroy_box(a);// a的所有权转移给函数形参,a变无效//println!("a contains: {}", a);// 报错!a无效
}
3.函数中返回一个变量作为返回值
函数的形参获得的所有权将在离开函数后就失效了。失效的数据就再也访问不到了。
为了解决所有权失效的问题,我们可以让函数将所有者返回给调用者。
fn destroy_box(c: Box<i32>) ->Box<i32> {println!("Destroying a box that contains {}", c);c
}
fn main() {let mut a = Box::new(5i32);// a 是一个指向堆分配的整数的指针a = destroy_box(a);// a的所有权转移给函数形参,a变无效println!("b contains: {}", a);// 报错!a无效
}
(三)复刻
复刻,英文是clone。也叫深复制或深拷贝。
有时候,我们需要创建一个值的完全独立的副本,而不是转让所有权。在这种情况下,可以使用复刻。
创建s1的副本s2,就像下图所示。s1和s2都拥有了独立的所有权。

示例:
fn main() {let s1 = String::from("hello");let s2 = s1.clone();println!("{} {}", s1, s2); // 正常打印 "hello hello"
}
创建了字符串"hello"的副本,赋值给s2,因此s1和s2都拥有了独立的所有权。
fn main() {let a = Box::new(5i32);let b = a.clone();println!("{}", a);println!("{}", b);
}
栈上的数据
看下例
fn main() {let a = 50;let b = a;println!("{}", a);println!("{}", b);
}
这段代码能编译通过。按照所有权转让规则的话,它应该编译错误才对,可是为什么能编译通过?
因为像整型这样的类型完全存储在栈上,并不需要占用那么大的内存,所以拷贝它的值是很快的。没有理由在创建变量b后使a无效。这里没有深浅拷贝的区别,所以这里不管是否调用clone,效果都一样。
Rust有一个Copy trait,可以用于存储在栈上的类型。如果一个类型实现了Copy trait,那么就不使用所有权转让,而是使用复刻。
那么哪些类型实现了Copy trait呢?
Rust不允许自身或其部分实现了Drop trait的类型使用Copy trait。
任何简单标量值的组合都可以实现Copy,任何不在堆上分配内存的类型都可以实现Copy。
如下是一些Copy的类型:
1.布尔类型,bool
2.数字类型,包括整数和浮点数,比如 u32,f64。
3.字符类型,char
4.元组,当且仅当,其包含的类型都实现Copy的时候。比如,(i32, i32) 实现了Copy,但 (i32, String) 就没有。
相关文章:
rust所有权
一、堆和栈 栈和堆都是程序运行时使用的内存,但是它们的结构不同。 1.栈 栈,英文是stack。是内存的一段区域。 栈是后进先出形式的。就像薯片桶,先放进去的一片只能后拿出来。 栈上存储的数据大小必须是已知且固定的。也就是说如果一个变量…...
Win10电脑任务栏没有蓝牙图标的简单解决方法
Win10电脑任务栏没有蓝牙图标怎么办?在Win10电脑中,用户有时候会发现任务栏上没有蓝牙图标了,这样就无法通过蓝牙图标快速打开蓝牙服务了。下面小编给大家介绍最简单的解决方法,帮助大家找回任务栏上面的蓝牙图标吧。 问题原因 反…...
判断编译器类型、编译器版本、操作系统。
目录 1. 判断编译器类型: 2. 判断编译器版本: 3. 判断操作系统: 总结: 1. 判断编译器类型: 可以使用预定义的宏来判断编译器类型。例如,__GNUC__ 宏用于判断是否使用了GCC 编译器,_MSC_VER…...
百度实习一面(知识图谱部门)
百度面经(知识图谱部)一面 1.自我介绍 介绍完了,打开共享,对着简历一点一点问 2.ffmpeg在项目中是怎么使用的 回答了ffmpeg在项目中使用的命令,用来干了什么 3.为什么使用toml配置,了解过yml配置吗&am…...
Oracle 数据库查询优化
目录 1. Oracle 数据库查询优化(上百万级记录如何提高查询速度)2. Oracle SQL 性能优化 40 条 | 收藏了! 1. Oracle 数据库查询优化(上百万级记录如何提高查询速度) 对查询进行优化, 应尽量避免全表扫描, 首先应考虑在 where 及 order by 涉及的列上建立索引应尽量避免在 wher…...
时序预测 | MATLAB实现POA-CNN-GRU鹈鹕算法优化卷积门控循环单元时间序列预测
时序预测 | MATLAB实现POA-CNN-GRU鹈鹕算法优化卷积门控循环单元时间序列预测 目录 时序预测 | MATLAB实现POA-CNN-GRU鹈鹕算法优化卷积门控循环单元时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 MATLAB实现POA-CNN-GRU鹈鹕算法优化卷积门控循环单元时间序…...
Java技术接单
今天给大家介绍一个阶段性(周期性)能获取一定收益的Java技术接单群,分享给大家!主要对搞Java的粉丝有帮助,因为可以赚点小钱,对Java技术的要求不高! 注意:首先进群不是免费的&#…...
多家企业发布基于大模型的AI产品,大模型应用落地哪家强?
https://m.mp.oeeee.com/a/BAAFRD000020230603805161.html “无产业不AI,无应用不AI。” 随着AI(人工智能)大模型技术落地,AI应用遍地开花。连日来,多家企业发布基于大模型的AI应用产品。身处“百模大战”时代&#x…...
如何在小程序中获取用户昵称、电话号,头像
一、如何获取昵称(获取微信昵称)以Taro框架为例 Taro框架中的组件Input的一个属性,type属性的值有一个nickname. 如果要拿到input的值,是要value结合onChange事件。 type"nickname" value{nickName} onChange{(value: …...
26606-2011 工业用氰乙酸甲酯 阅读笔记
声明 本文是学习GB-T 26606-2011 工业用氰乙酸甲酯. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本标准规定了工业用氰乙酸甲酯的要求、试验方法、检验规则、标志、包装、运输、贮存和安全。 本标准适用于以氯乙酸、氰化钠、甲醇等为原料…...
微软开源 windows-drivers-rs, 用 Rust 开发 Windows 驱动程序
目录 1. 微软开源 windows-drivers-rs, 用 Rust 开发 Windows 驱动程序 1. 微软开源 windows-drivers-rs, 用 Rust 开发 Windows 驱动程序 Microsoft Azure 首席技术官兼著名 Windows 软件开发人员 Mark Russinovich 在社交平台上宣布, 启动了一个名为 windows-drivers-rs 的新…...
Java中判断字符串是否为合法数字
问题 最近遇到需要将String转BigDecimal的场景。 解决思路 利用NumberUtils.isCreatable判断是否为合法数字,然后,对字符串进行数字转换。注意:这里的NumberUtils类是org.apache.commons.lang3.math库里面的类。 Java if (NumberUtils.i…...
[LeetCode] Hard-2251. 花期内花的数目 - 二分查找/有序数组
Problem: 2251. 花期内花的数目 2251. 花期内花的数目 思路解题方法Code 思路 看题目应该是一道比较经典的差分,本来准备拿差分数组做的,后来搂了一眼题解,发现用二分的方法更简单 解题方法 此题有一种很简便的方法,第i个人到…...
VUE3父子组件传值defineProps() 和 defineEmits()
defineProps 和 defineEmits 都是只能在<script setup>中使用的编译器宏。他们不需要导入,且会随着 <script setup> 的处理过程一同被编译掉。 官网传送门 父组件向子组件传值 defineProps 是 Vue3 中一种新的组件数据传递方式,可以用于在…...
OmniPlan Pro 4 for Mac:引领项目管理的创新与高效
OmniPlan Pro 4是一款强大且高效的项目管理工具,专为Mac用户设计。它提供了一套综合性的解决方案,帮助用户在Mac上便捷地进行项目规划、追踪和管理。凭借其直观的界面,用户可以快速上手,并且能充分利用这款工具的各种功能。 规划…...
封装JDBC,实现简单ORM框架
本文将封装JDBC的操作,实现简单的ORM框架,提供3种风格的api来给用户使用(1.原生jdbcSqlBuilder;2.类似jpa和mp的;3.注解接口方法) 代码仓库:malred/IFullORM 1. 原生JDBCsql构建器 第一步&…...
监控与运维,主流it运维监控工具
IT监管和运行维护已成为企业经营的关键环节。本文将详细介绍IT监管和运行维护的必要性、主要功能和实施策略,帮助企业实现数据安全和高效运行。 IT监管和运行维护的必要性 确保企业数据安全 IT监控系统可以实时监控企业网络、服务器、存储等关键设备的运行情况&…...
基于Matlab实现全局优化算法
Matlab是一种非常强大的数学建模和计算工具,它提供了许多优化算法的实现。全局优化算法是一种能够找到全局最优解的优化算法,相对于局部优化算法来说,具有更强的全局搜索能力。在本文中,我们将介绍如何使用Matlab实现全局优化算法…...
Kafka 笔记 (Non-Root/Container)
目录 1. Kafka 笔记 (Non-Root/Container)1.1. 启动1.2. bitnami/kafka1.2.1. Non-Root Containers 1. Kafka 笔记 (Non-Root/Container) 1.1. 启动 Kafka 需要与 ZooKeeper 一起启动: Kafka with ZooKeeper Run the following commands in order to start all services in…...
【Pytest】跳过执行之@pytest.mark.skip()详解
一、skip介绍及运用 在我们自动化测试过程中,经常会遇到功能阻塞、功能未实现、环境等一系列外部因素问题导致的一些用例执行不了,这时我们就可以用到跳过skip用例,如果我们注释掉或删除掉,后面还要进行恢复操作。 1、skip跳过成…...
Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...
如何在看板中有效管理突发紧急任务
在看板中有效管理突发紧急任务需要:设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP(Work-in-Progress)弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中,设立专门的紧急任务通道尤为重要,这能…...
(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...
Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...
鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/
使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题:docker pull 失败 网络不同,需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...
智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制
在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...
初探Service服务发现机制
1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能:服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源…...
uniapp 小程序 学习(一)
利用Hbuilder 创建项目 运行到内置浏览器看效果 下载微信小程序 安装到Hbuilder 下载地址 :开发者工具默认安装 设置服务端口号 在Hbuilder中设置微信小程序 配置 找到运行设置,将微信开发者工具放入到Hbuilder中, 打开后出现 如下 bug 解…...
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么?它的作用是什么? Spring框架的核心容器是IoC(控制反转)容器。它的主要作用是管理对…...
