第 1 章 从自动释放到所有权
这一章要解决一个看似悖论的问题:如果不靠人手写每一次 free,也不靠垃圾回收(Garbage Collection,GC)在运行时扫描或计数,程序怎么可能既自动回收内存、又保证绝对安全?
为了让你不受语法细节干扰,本章的六节是一场连续的第一性原理推演——前五节不写实际的 Rust 语法,也不预先罗列「所有权」「借用」这些术语,而是顺着物理约束一步步把内存回收模型搭出来;最后一节再将这套机制对上 Rust 的原生概念,并盘点尚未解决的边界问题。从下一章起,我们打开编译器,在 Rust 代码里逐项核对这套模型。
六节分三段推进:
- 第一段:把问题与底图摆出来(第 1~2 节)。 困难三角先点出「自动回收、但非 GC」的破局方向;栈与堆接着建立内存布局的心智底图:栈帧随函数返回自动消失,只有堆上申请来的资源需要回收,而操控堆的那个栈变量恰恰有确定的作用域终点(
})。 - 第二段:立起最简模型并导出 Move(第 3 节)。 先定下「栈变量离开作用域就释放它指向的堆」,随即用一行最普通的赋值
t = s测出双重释放冲突,逼出「同一块堆只能由一个变量负责释放」的结论,以及同一个=在 Copy 与 Move 上的分野。 - 第三段:补上协作与防悬垂检查,完成概念归一(第 4~6 节)。 只靠 Move 连调一个只读函数都会把参数作废,于是设计出只存栈地址、剥离了释放责任的引用(
&T);再针对「原变量先退场导致引用悬空」的漏洞,让编译器在编译期自动比对两者的有效范围(生命周期)。最后一节复盘整条推演链,把我们发明的机制对上 Rust 的所有权、借用与生命周期。
读完这一章,不需要死记任何语法口诀,你应该能用自己的话讲清三件事:
- 为什么栈不需要回收,而堆资源必须有人负责归还?
- 为什么同样是一行赋值
=,整数两边都能继续用,带堆资源的字符串却必须让旧变量失效? - 为什么引用可以自由复制共享,却必须在编译期约束它的有效区间?