前面有一篇文章介绍了什么是 Rust 的生命周期?这里补充一些关于 Rust 的生命周期不容易被注意到的细节。
因为我水平有限,有的概念可能不是很全面,甚至可能有偏差,还请多多指点。
生命周期是完全静态的
Rust 的看家本领就是静态检测,所有实例的生命周期都是在编译时就被确定好的。
所以不要问:“为什么生命周期不能根据实际情况自动确定?”因为真的做不到!
let 可以绑定所有权
除了绑定所有者和数据外,let 还可以绑定所有者和数据之间的所有权。绑定了所有权,也就绑定了生命周期。
这是理所当然的事实,但是经常被人忽略。
形参与实参的生命周期是相互绑定的
与 let 相似,函数中的形式参数与实际参数的生命周期是相互绑定的。同样的,函数返回值和函数实体的拥有者的生命周期也是相互绑定的,因为返回值的生命周期与函数实体相互绑定,而函数实体与拥有者相互绑定。
举个例子:
| |
x 与a 相互绑定,c 与 sum() 与 a + b 相互绑定。
| |
结构体中也是类似的:
| |
x 与 y 相互绑定,结构体 Foo 与 f 相互绑定。
| |
这同样也是理所当然但容易被人忽视的事实,这里提出来也是为了给下一条做铺垫。
生命周期标记的影响不仅仅是函数 (结构体) 内部
准确的说应该是生命周期标记可以通过影响函数 (结构体) 内部来对函数实体的拥有者和传入的实际参数产生影响。具体原因就是上面提到的形式参数与实际参数的生命周期相互绑定,函数返回值和函数实体的拥有者的生命周期相互绑定。
举个例子:
| |
生命周期参数将 x 的生命周期与 results 相互绑定,而 x 与 a 相互绑定,results 与 c 相互绑定,所以 c 的生命周期与 a 是相互绑定的!!就像三国杀中的“铁索连环”一样
| |
根据关系我们可以很容易发现,a 必须活得比 c 长,不然就会报错。
从整体来考虑生命周期,显然更容易理解什么时候应该使用生命周期标注,什么时候不应该使用。
生命周期标注的作用不是“续命”
生命周期标注只是注释出:“谁应该比谁活得更长 (或者相等)”,如果实际情况与标注不相符,编译器会报错。
长生命周期是短生命周期的子类型
与直觉有所不同。显式生命周期标注是泛型参数一种,但是有协变的概念。