当前位置:网站首页>每日一R「02」所有权与 Move 语义
每日一R「02」所有权与 Move 语义
2022-08-09 21:54:00 【InfoQ】
01-所有权原则
- c / c++ 中,堆内存的分配和释放,需要开发者自觉地去维护,使用 malloc / free 来显式地申请和释放堆内存。这样最大的问题就在于,对内存管理完全交由开发者自行维护,而人总是容易犯错的,极容易发生内存泄漏等问题。
- java 采用了与 c / c++ 不一样的方式来管理堆内存。当 new 关键字时,JVM 会帮助开发者在堆上分配空间。堆空间的回收 JVM 通过 GC 来完成。这样做虽然可以很大程度上确保内存安全,但 GC 需要消耗额外的资源,而且还存在 Stop the world 的问题。
- 一个值只能被一个变量所拥有,这个变量被称为所有者。
- 一个值同一时刻只能有一个所有者。
- 当所有者离开作用域,其拥有的值被丢弃。
- 栈内存。
- 栈中存储的是固定长度的类型值,例如i32 / u32 / u8 等。对于这块空间中的内容,它的所有权由某个变量拥有,这个变量称为这块内存的所有者(第一条)。例如
let x: u32 = 5;
会在栈空间中分配 32 位长度的内存,并将这块内存的内容设置为 5。同样,let y: u8 = 1;
会在栈空间中分配 8 位长度的内存,并将这块内存的内容设置为 1。
- 所有权第二条怎么理解呢?就是说栈空间中的某块内存(值)同一时刻只能被一个变量拥有。从代码上我们理解一下:
let x: u32 = 10; let y = x;
前面一句与上面一样,在栈空间中分配一块内存,并将这块内存的所有权给 x。第二句会在栈空间中分配同样 x 同样大小的空间并将 x 中的内容拷贝一份到这块空间(Copy 语义,会在后面的课程中学习到)。y 是这块新空间的所有者,与所有权原则第一条自洽。
- 变量的作用域指从变量声明开始,到变量所在代码块结束这段时间。当变量离开其作用域,变量拥有的内存空间被释放,这点也不难理解。
- 堆内存。
- 堆中存储的是长度可变的值,例如 Vec,String等。对于这块内存空间,变量是通过什么方式来体现所有权的呢?《Rust语言圣经》是这样描述的:
String
类型是一个复杂类型,由存储在栈中的堆指针、字符串长度、字符串容量共同组成,其中堆指针是最重要的,它指向了真实存储字符串内容的堆内存,容量是堆内存分配空间的大小,长度是目前已经使用的大小。
- 从上面的描述中我们可以了解到,对于堆中长度可变的值,Rust 通过栈上固定长度的“胖指针”实现了对堆上值的所有权。
- 从代码角度理解一下第二条,
let s1 = String::from("hello"); let s2 = s1;
前面一句代码,会再堆上分配一块空间存储”hello”,并在栈上分配一个胖指针,它存储有指向堆中空间的堆地址、字符串长度、字符串容量。第二句中,会在栈上创建一个胖指针,胖指针 s1 的内容(堆地址、长度、容量)会被拷贝到 s2 上,堆中的”hello”并不会被拷贝。第二句执行后,s1 便不再拥有堆中内容”hello”的所有权,任何通过 s1 访问堆中内容的尝试都会被 Rust 编译器拒绝。通过这种方式,Rust 可以保证堆中空间有且仅有一个变量引用,从而解决了堆中内存回收的问题。
- 注:可能会有人注意到,
let s1 = s;
与上面的let y = x;
的语义不太一样呢?在 Rust 中,固定长度的类型,包括整型、字符型等,甚至数组[T; n],都是固定长度的,它们存储在栈内存中;而非固定长度类型,例如 String、Vec等,都是存储在堆上的。对于前者,它们是实现了 Copy trait 的,而后者则没有。原因是,如果后者实现了,会违背有且仅有一个所有者的原则。
- 当胖指针变量离开了它的作用域,它指向的堆内存会被回收。这样 Rust 就不用像 Java 一样,还需要借助 GC 来回收堆内存;也避免了像 C/C++ 一样需要人为地回收内存,从而提高了安全性。
02-Move 语义
let s1 = String::from("hello");
let s2 = s1;

fn takes_and_gives_back(a_string: String) -> String { // a_string 进入作用域
a_string // 返回 a_string 并移出给调用的函数
}
fn main() {
let s = String::from("hello");
let s1 = takes_and_gives_back(s);
}
边栏推荐
- The overall construction process of the Tensorflow model
- 孙正义亏掉1500亿:当初投贵了
- [Cloud Native] 4.2 DevOps Lectures
- 【EF】 更新条目时出错。有关详细信息,请参见内部异常。[通俗易懂]
- nvm下node安装;node环境变量配置
- AI Knows Everything: Building and Deploying a Sign Language Recognition System from Zero
- Xiaohei leetcode's refreshing rainy day trip, just finished eating Yufei Beef Noodles, Mala Tang and Beer: 112. Path Sum
- Several ways to draw timeline diagrams
- 论文解读(DropEdge)《DropEdge: Towards Deep Graph Convolutional Networks on Node Classification》
- Metasploit常用命令、技术功能模块
猜你喜欢
五星控股汪建国:以“植物精神”深耕赛道,用“动物精神”推动成长
[Microservice~Nacos] Configuration Center of Nacos
重装系统后新建文本文档打不开怎么办
leetcode 刷题日记 计算右侧小于当前元素的个数
Install win virtual machine on VMware
Simple questions peek into mathematics
阿里云架构师金云龙:基于云XR平台的视觉计算应用部署
好未来,想成为第二个新东方
How to Make Your Company Content GDPR Compliant
nvm下node安装;node环境变量配置
随机推荐
OpenMLDB + Jupyter Notebook:快速搭建机器学习应用
[Implementation of the interface for adding, deleting, checking, and modifying a double-linked list]
Interpretation of the paper (DropEdge) "DropEdge: Towards Deep Graph Convolutional Networks on Node Classification"
简单问题窥见数学
Evolution of MLOps
【微服务~Nacos】Nacos服务提供者和服务消费者
数独 | 回溯-7
《强化学习周刊》第57期:DL-DRL、FedDRL & Deep VULMAN
聊天尬死名场面,你遇到过吗?教你一键获取斗图表情包,晋升聊天达人
MLOps的演进历程
任务流执行器是如何工作的?
为什么这么多人都想当产品经理?
String hashing (2014 SERC J question)
国内手机厂商曾为它大打出手,如今它却最先垮台……
论文解读(DropEdge)《DropEdge: Towards Deep Graph Convolutional Networks on Node Classification》
几种绘制时间线图的方法
Synchronization lock synchronized traces the source
SQLi-LABS Page-2 (Adv Injections)
APP自动化测试框架-UiAutomator2基础入门
Cookie, session, token