为什么要有所有权

所有权是Rust保证内存安全的方式。

为什么不用GC回收呢?

首先让我了解GC的回收的机制 在偌大的内存上存活着无数对象,GC 之前需要准确将这些对象标记出来,分为存活对象与垃圾对象。这个过程一旦少标记,那就只能等待下次 GC标记,再回收,这样将会影响 GC 效率。另外决不能错标记,将正常存活对象标记为垃圾。一旦回收正常存活的对象,可能就会引起程序各种崩溃。

GC 会引来性能、内存占用以及 Stop the world 等问题。

stop the world (指的是GC事件发生过程中,会产生应用程序的停顿。停顿产生时整个应用程序线程都会被暂停,没有任何响应, 有点像卡死的感觉,这个停顿称为STW)

手动管理内存的分配和释放的问题

手动管理内存释放的方式很容易导致内存溢出与泄露,如c++,上手难度也比较大。

Rust中使用所有权来管理内存。编译器在编译时会根据一系列规则进行检查,在编译时解决错误,因此相比之下提高了程序运行时的效率。

栈与堆

要理解Rust必须要先搞清楚stack与heap。 栈和堆的核心目标就是为程序在运行时提供可供使用的内存空间。

栈(stack)

栈中数据:后进先出,增加数据叫做进栈,移出数据则叫做出栈

栈中的所有数据都必须占用已知且固定大小的内存空间 想象一下一叠盘子:当增加更多盘子时,把它们放在盘子堆的顶部,当需要盘子时,再从顶部拿走。不能从中间也不能从底部增加或拿走盘子

堆(heap)

与栈不同,对于大小未知或者可能变化的数据,我们需要将它存储在堆上。

向堆上存放数据时:

  1. 先申请一定大小的空间
  2. 申请完毕返回该地址的指针
  3. 指针会被放在栈上
  4. 通过栈拿到指针去访问堆

性能区别

写入方面:入栈比在堆上分配内存要快,因为入栈时操作系统无需分配新的空间,只需要将新数据放入栈顶即可。相比之下,在堆上分配内存则需要更多的工作,这是因为操作系统必须首先找到一块足够存放数据的内存空间,接着做一些记录为下一次分配做准备。 读取方面:得益于 CPU 高速缓存,使得处理器可以减少对内存的访问,高速缓存和内存的访问速度差异在 10 倍以上!栈数据往往可以直接存储在 CPU 高速缓存中,而堆数据只能存储在内存中。访问堆上的数据比访问栈上的数据慢,因为必须先访问栈再通过栈上的指针来访问内存。 因此,处理器处理和分配在栈上数据会比在堆上的数据更加高效。

所有权与堆栈

当你的代码调用一个函数时,传递给函数的参数(包括可能指向堆上数据的指针和函数的局部变量)依次被压入栈中,当函数调用结束时,这些值将被从栈中按照相反的顺序依次移除。 因为堆上的数据缺乏组织,因此跟踪这些数据何时分配和释放是非常重要的,否则堆上的数据将产生内存泄漏 —— 这些数据将永远无法被回收。这就是 Rust 所有权系统为我们提供的强大保障。 对于其他很多编程语言,你确实无需理解堆栈的原理,但是在 Rust 中,明白堆栈的原理,对于我们理解所有权的工作原理会有很大的帮助

所有权规则

  1. Rust 中每一个值都被一个变量所拥有,该变量被称为值的所有者
  2. 一个值同时只能被一个变量所拥有,或者说一个值只能拥有一个所有者
  3. 当所有者(变量)离开作用域范围时,这个值将被丢弃(drop)

数组是放在栈上的

当结构体的属性发生转移时

基本类型会发生copy,引用类型会发生转移。

  1. let user2 = User {
  2. email: String::from("another@example.com"),
  3. ..user1 //基本类型会发生copy,引用类型会发生转移。
  4. };

6.Rust中的所有权 - 图1