rust 生命周期
1.什么是生命周期
Rust 中的每一个引用都有其 生命周期(lifetime),也就是引用保持有效的作用域。大部分时候生命周期是隐含并可以推断的,正如大部分时候类型也是可以推断的一样。在函数或者方法签名中表示引用的生命周期,通过生命周期注解描述引用有效的作用域,从而避免悬垂引用和数据竞争等问题。
Rust 编译器有一个 借用检查器(borrow checker),用来确保所有的借用都是有效的。
//悬垂引用
{
let r;
{
let x = 5;
r = &x;
}//x 已经离开作用域
println("r = {}", r);
}
//数据竞争
2. 生命周期语法
生命周期参数名称必须以撇号(')开头,其名称通常全是小写,类似于泛型其名称非常短。'a 是大多数人默认使用的名称。生命周期参数标注位于引用的 & 之后,并有一个空格来将引用类型与生命周期标注分隔开
@i32
@'a i32 //带有显式生命周期的引用
@'a mut i32 //带有显式生命周期的可变引用
编译器采用三条规则来判断引用何时不需要明确的标注
第一条规则是 每一个是引用的参数都有它自己的生命周期参数
第二条规则是 如果只有一个输入生命周期参数,那么它被赋予所有输出生命周期参数
第三条规则是 如果方法有多个输入生命周期参数并且其中一个参数是 &self 或 &mut self, 那么所有输出生命周期参数被赋予 self 的生命周期
//第一条规则
fn first_word<'a>(s: &'a str) -> &str { }
//第二条规则
fn first_word<'a>(s: &'a str) -> &'a str { }
//第三条规则
#![allow(unused)]
fn main() {
struct ImportantExcerpt<'a> {
part: &'a str,
}
impl<'a> ImportantExcerpt<'a> {
fn announce_and_return_part(&self, announcement: &str) -> &str {
println!("Attention please: {}", announcement);
self.part
}
}
}
生命周期长度
// 'a 比 'b 生命周期长;
struct Demo<'a,'b:'a,T>{
a:&'a T,
b:&'b T,
}
// T 比 ‘a 长
struct Demo2<'a, T:'a>{
r:&'a T
}
//也可以这样写
struct Demo3<'a, T>{
r:&'a T
}
//引用的生命周期从借用处开始,一直持续到最后一次使用的地方。
let mut s = String::from("hello");
let r1 = &s;
let r2 = &s;
println!("{} {}", r1, r2);
let r3 = &mut s; //r1,r2 结束后不在引用生命周期结束
println!("{}", r3);
reborrow 再借用
#[derive(Debug)]
struct Point {
x: i32,
y: i32,
}
impl Point {
fn move_to(&mut self, x: i32, y: i32) {
self.x = y;
self.y = x;
}
}
fn main() {
let mut p = Point { x: 0, y: 0 };
let r = &mut p;
let rr = &*r;
println!("{:?}", rr);//再次借用后,后面没有在使用
r.move_to(10, 10);
println!("{:?}", r);
}
生命周期规则消除
//'_ 生命周期表示 BufReader 有一个不使用的生命周期,我们可以忽略它,无需为它创建一个名称。
impl Reader for BufReader<'_> {
// methods go here
}
静态生命周期
‘static 其生命周期能够存活于整个程序期间。所有的字符串字面量都拥有 'static 生命周期
&‘static 和 T:&'static
&'static 生命周期针对的仅仅是引用,而不是持有该引用的变量,对于变量来说,还是要遵循相应的作用域规则 :
如果你需要添加 &'static 来让代码工作,那很可能是设计上出问题了
如果你希望满足和取悦编译器,那就使用 T: 'static,很多时候它都能解决问题
use std::fmt::Display;
fn main() {
let mark_twain = "Samuel Clemens";
print_author(mark_twain);
print_2(&mark_twain);
}
//&'static
fn print_author(author: &str) {
println!("{}", author);
}
// T:&'static 生命周期约束
fn print_2<T: Display + 'static>(meeage: &T) {
println!("{}", meeage);
}