rust 生命周期

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);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值