前面有一篇文章介绍了什么是 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
长,不然就会报错。
从整体来考虑生命周期,显然更容易理解什么时候应该使用生命周期标注,什么时候不应该使用。
生命周期标注的作用不是“续命”
生命周期标注只是注释出:“谁应该比谁活得更长 (或者相等)”,如果实际情况与标注不相符,编译器会报错。
长生命周期是短生命周期的子类型
与直觉有所不同。显式生命周期标注是泛型参数一种,但是有协变的概念。