生命周期-Rust
生命周期-Rust
xiu生命周期是为了避免悬垂引用
了每一个引用&
都有一个生命周期
悬垂引用
悬垂引用指的是一个引用指向的内存已经被释放或者不再有效,编程者如果在这个时候还尝试访问这个失效的引用就会发生错误
r 引用的值在尝试使用之前就离开了作用域
借用检查器
Rust 编译器有一个 借用检查器(borrow checker),它比较作用域来确保所有的借用都是有效的
r 的生命周期标记为 ‘a 并将 x 的生命周期标记为 ‘b
被引用者的生命周期要大于或者等于引用者的生命周期,或者直接将所有权交给引用者
函数中的泛型生命周期
编写一个返回两个字符串 slice 中较长者的函数
我们定义这个函数的时候,并不知道传递给函数的具体值,所以也不知道到底是 if 还是else 会被执行
1 | &i32 // 引用 |
单个的生命周期注解本身没有多少意义,因为生命周期注解告诉 Rust 多个引用的泛型生命周期参数如何相互联系的
1 | fn main() { |
1 | fn main() { |
深入理解生命周期
如果将 longest 函数的实现修改为总是返回第一个参数而不是最长的字符串 slice,就不需要为参数 y 指定一个生命周期
1 | fn longest<'a>(x: &'a str, y: &str) -> &'a str { |
当从函数返回一个引用,返回值的生命周期参数需要与一个参数的生命周期参数相匹配。如果返回的引用没有 指向任何一个参数,那么唯一的可能就是它指向一个函数内部创建的值。然而它将会是一个悬垂引用,因为它将会在函数结束时离开作用域。这种情况即使指定生命周期编译也通不过,如下例子
1 | fn longest<'a>(x: &str, y: &str) -> &'a str { |
我们尝试从函数返回一个 result 的引用。无法指定生命周期参数来改变悬垂引用,而且 Rust 也不允许我们创建一个悬垂引用。在这种情况,最好的解决方案是返回一个有所有权的数据类型而不是一个引用,这样函数调用者就需要负责清理这个值了。
结构体中的生命周期
1 | struct ImportantExcerpt<'a> { |
这个注解意味着 ImportantExcerpt 的实例不能比其 part 字段中的引用存在的更久
生命周期省略
函数或方法的参数的生命周期被称为 输入生命周期(input lifetimes),而返回值的生命周期被称为 输出生命周期(output lifetimes)
三条默认的生命周期规律
1 | 1、函数有一个引用参数的就有一个生命周期参数:fn foo<'a>(x: &'a i32),有两个引用参数的函数就有两个不同的生命周期参数,fn foo<'a, 'b>(x: &'a i32, y: &'b i32),依此类推 |
静态生命周期
‘static,其生命周期能够存活于整个程序期间
总结
在同一函数中指定泛型类型参数、trait bounds 和生命周期
1 | fn main() { |