要讲清楚 所有权,必须得讲清楚两个基本概念:
栈(Stack)与堆(Heap)
估计高手看这篇如同废话,请直接跳过,但不说清楚下面就没有办法讲 ownership了。
栈和堆都是代码在运行时可供使用的内存,但是它们的结构不同。栈是很有序的结构。栈以放入值的顺序存储值并以相反顺序取出值。这也被称作?后进先出(last in, first out)。
栈中的所有数据都必须占用已知且固定的大小。在编译时大小未知或大小可能变化的数据,要改为存储在堆上。
因为堆里的数据有大有小,所以堆是缺乏结构的:当向堆放入数据时,你要先请求一定大小的空间,还记得C语言的malloc,calloc吧。内存分配器(memory allocator)在堆的某处(不一定是哪里)找到一块足够大的空位,把它标记为已使用,并返回一个表示该位置地址的 让人又爱又恨的?指针(pointer)。这个过程称作?在堆上分配内存(allocating on the heap),有时简称为 “分配”(allocating)。
注意区别一下,指针本身是放在栈里的,因为指向放入堆中数据的指针是已知的并且大小是固定的。
想象一下你和朋友去餐馆吃饭。你向服务员说明有几个人,服务员会找到(allocating)一个够大的空桌子并领你们过去。如果有朋友来迟了,他也可以通过询问你们大桌子的位置(pointer 指针)来找到你们坐在哪。
比如下面这个代码段:
let s1 = String::from("hello");
在内存里是这样的,s1在栈里,“hello”在堆里,s1指向“hello”所在的位置:
?
当你的代码调用一个函数时,传递给函数的值(包括可能指向堆上数据的指针)和函数的局部变量被压入栈中。当函数结束时,这些值被移出栈。
如何跟踪哪部分代码正在使用堆上的哪些数据,最大限度的减少堆上的重复数据的数量,以及清理堆上不再使用的数据确保不会耗尽空间,这些问题正是 所有权(ownership)系统要处理的。也是Java,Python的垃圾回收机制做的事情。
一旦理解了所有权(ownership),就不需要经常考虑栈和堆了,不过明白了所有权的主要目的就是为了管理堆数据,(栈那么整齐,是不需要我们特殊管理的),就能够理解为什么所有权要以这种方式工作。