rust-生命周期
前言
先说大白话,rust 的生命周期标注,是为了明确多个变量的生命周期是否一致,仅此而已,因为如果rust不知道多个变量的生命周期是否一致,它无法确的知道这个变量是否已经被释放。这个下面再细说,先说有什么用。
rust当中,的两个重要概念:借用和生命周期分别代是在:
- 栈变量,需要关注【所有权】
- 引用(指针),需要关注【生命周期】
Rust 的每个引用都有自己的生命周期,生命周期指的是引用保持有效的作用域。
大多数情况下,引用是隐式的、可以被推断出来的,但当引用可能以不同的方式互相关联时,则需要手动标注生命周期。
这里重点就是以不同的方式互相关联时。
大多数情况下,rust 可以自己推断出引用的生拿周期,也就是只有在一些rust无法自行推断的情况下,才需要手动标注生命周期。
生命周期
Rust 中的每一个引用都有其生命周期(lifetime),也就是引用保持有效的作用域。
大部分时候生命周期是隐含并可以推断的,正如大部分时候类型也是可以推断的一样。
类似于当因为有多种可能类型的时候必须注明类型,也会出现引用的生命周期以一些不同方式相关联的情况,所以 Rust 需要我们使用泛型生命周期参数来注明他们的关系,这样就能确保运行时实际使用的引用绝对是有效的。
这里还有一个需要关注的点就是关系,也就多个引用之前的关系,才是导致rust无法明确推断出引用生命周期的最根本原因。
反例
这段代码看着很正常,但是实际上,编译会报错,类为这里调用longest
时,longest
无法确认x
、y
的生命周期。
为什么无法确认?
因为longest
是被调用的方法,它肯定没法知道,这两个传入在main
方法的中的生命周期。
好比,你写一个接口给外部调用,你也无法知道调你的服务,传入的两个变量,在那个服务中的生命周期。
但是在rust中,又非常强调安全性,它必须清楚每个引用的明确的生命周期。
所以这个活,就落在了开发者身上,必须明确告诉rust,每个引用的生命周期。
1 | fn main() { |
报错如下:missing lifetime specifier
1 | error[E0106]: missing lifetime specifier |
上面看着很正常呀,哪里有问题?
生命周期标注
即然rust
不智能,那只能开发者辛苦一点,手动来标注了。rust
的生命周期标注语法,只能表示引用的生命周期,而不能、不会改会引用的生命周期。
命名规则:
'a
以 ' 开头- 全小写
1 | &i32 // 引用 |
单个的生命周期注解本身没有多少意义,因为生命周期注解告诉 Rust 多个引用的泛型生命周期参数如何相互联系的。
函数签名中的生命周期注解
描述了 x、y 之间的关系。
longest 函数定义指定了签名中所有的引用必须有相同的生命周期'a
1 | fn main() { |
只有一个参数,要不要标注
那当然是不要啦!!
生命周期注解告诉编译器引用参数的有效范围,以便编译器可以检查代码是否合法。
但是,在某些情况下,编译器可以自动推断出引用参数的生命周期,因此不需要显式注解。
当一个函数或方法需要一个借用参数时,如果该参数的生命周期与函数或方法的生命周期相同,则可以省略生命周期注解。例如:
这个例子,标不标注都是成立的。
1 | fn foo<'a>(x: &'a i32) -> &'a i32 { |
但是,如果函数或方法需要一个借用参数,并且该参数的生命周期与函数或方法的生命周期不同,则必须显式注解参数的生命周期。
1 | struct Foo<'a> { |
在这个例子中,方法 bar 的第二个参数 y 的生命周期不同于 Foo 结构体中的引用 x 的生命周期,所以嘛必须显式注解参数的生命周期。
总结
人多了,就容易产生纠分,变量形参多了,也是这样,所以才需要标注,分个明白。