栈内存和堆内存¶
1. 概述¶
所有权是Rust最独特的特性,它让Rust无需GC就可以保证内存安全。
1.1. 什么是所有权?¶
-
Rust的核心特性就是所有权
-
所有程序在运行时就必须管理它们使用内存的方式:有些语言有垃圾回收机制,在程序运行时,它们会不断地寻找不再使用的内存,将内存收集和释放,如Java;在其他语言中,程序员必须显示地分配和释放内存,如C/C++。
-
Rust使用了第三种方式:内存是通过所有权来管理的,其中包含一组编译器时检查的规则。当程序运行时,所有权特性不会减慢程序的运行速度。
2. 栈内存和堆内存(stack vs heap)¶
在rust这样的系统级编程语言里,一个值是在stack上还是在heap上对语言的行为和你为什么要做某些决定是有更大的影响。
在我们运行代码的时候,stack和heap都是可用的内存,但它们的结构很不相同。
2.1. 存储数据¶
stack按值的接收顺序来存储,按相反的顺序将它们移除(后进先出,LIFO)
-
添加数据叫压栈或入栈
-
移除数据叫做出栈或弹出栈
所有存储在stack上的数据必须是已知的固定大小,编译时大小未知的数据或者运行时大小可能发生改变的数据必须放在heap上。
heap内存的组织性差一些
-
当你把数据放入heap时,你会请求一定数量的空间
-
操作系统在heap里找到一块足够大的空间,把它标记为在用,并返回一个指针,也就是这个空间的地址
把值压到stack上不叫分配,因为指针是已知固定大小的,可以把指针放在stack上。但如果想要实际数据,你必须用指针来定位。把数据压到stack上要比heap上分配快得多,因为操作系统不需要寻找存储新数据的空降,那个位置永远在stack的顶端;在heap上分配空间需要做更多的工作,操作系统首先需要找到一个足够大的空间来存储数据,然后做好记录方便下次再分配。
2.2. 访问数据¶
-
访问heap中的数据要比访问stack中的数据慢,因为需要通过指针才能找到heap中的数据,多了指针跳转的环节,属于间接访问。对于现代的处理器来说,由于缓存的缘故,如果指令在内存中跳转的次数越少,那么速度就越快
-
如果数据排列的距离比较近,那么处理器的处理速度就会更快一些(stack上)
-
如果数据之间的距离比较远,那么处理速度就会慢一些(heap上),在heap上分配大量空间,也是需要时间的
2.3. 函数调用¶
当代码调用函数时,值被传入函数(也包括指向 heap 的指针),函数本地的变量被压在 stack 上,当函数结束后,这些值会从stack上弹出。
3. 所有权存在的原因¶
所有权解决的问题:
-
跟踪代码哪些部分正在使用 heap 的哪些数据
-
最小化heap上的重复数据
-
清理heap 上未使用的数据以避免空间不足
一旦明白了所有权,那么就不需要经常去想stack或heap了。但是知道管理heap数据是所有权存在的原因,这有助于解释它为什么会这样工作!