刚学 Rust 时,我把所有权当成一条要背下来的规则。真正上手之后才发现,它更像是三种互相支撑的看待方式,任意一种卡住了,换另一种通常就通了。
一、谁负责释放
第一个模型最朴素:每一块内存,都有且只有一个变量为它的释放负责。move 就是把这份责任交出去,交出去之后你就不能再用它。编译器不过是在替你追踪「责任在谁手上」。
二、借用是一份契约
&T 和 &mut T 不是指针的语法糖,而是一份有期限的契约:在借用存活期间,所有者承诺不动这块数据。共享借用可以有很多份,可变借用只能有一份——这正是「读读不冲突,写要独占」的并发直觉,只是被提前到了编译期。
三、生命周期是关系,不是时长
最后一个模型花了我最久:生命周期标注不是在说「活多久」,而是在说「谁不能比谁先死」。'a 只是给编译器一个名字,去表达引用之间的先后约束。想清楚这一点,那些 <'a> 就不再是噪音。