Skip to content

Rust lifetime 生命周期

  • 变量的生命周期局限在作用域内,如果要在作用域之外使用改变了,那么我们就需要标注?

Borrow Checker 借用检查器

代码块

Rust 编译器会在编译的时候比较作用域变量的生命周期。 Rust 官方文档中有如下示例:

rust
{
    let r;                // ---------+-- 'a
                          //          |
    {                     //          |
        let x = 5;        // -+-- 'b  |
        r = &x;           //  |       |
    }                     // -+       |
                          //          |
    println!("r: {}", r); //          |
}

从中我们可以看出,里面括号里的代码块,变量 x 的作用域局限在里面的括号里,所以它的生命周期明显只有在这个括号里,对比变量 r,r 的生命周期要比 x 长,这个时候又将 x 的引用赋值给 r,编译器会报错,因为后面的println!("r: {}", r);打印的 r,其实是 x。

在函数中分配生命周期

函数传参数,参数为引用,为什么要传引用呢?不想让函数拥有参数的所有权。

rust
&i32                // 这是一个引用
&'a i32             // 这是一个有着详细生命周期的引用
&'a mut i32         // 这是一个有着详细生命周期的可变引用

fn longest<'a>(x: &'a str, y: &str) -> &'a str {
    x
}

// 错误案例
fn longest<'a>(x: &str, y: &str) -> &'a str {
    let result = String::from("really long string");
    result.as_str()
}

为什么的个函数longest会报错呢?原因是 result 的生命周期要比'a短。

在结构体定义里标记生命周期

哪些规则不需要为引用声明生命周期(lifetime elision rules)生命周期省略

  • 每一个引用都有一个生命周期
  • 在函数或者方法参数中,生命周期被称作输入生命周期,相反,返回值的被称作输出生命周期。

生命周期省略规则

第一条适用于输入生命周期,后面两条则适用于输出生命周期。适用于fnimpl块。只有满足如下三点,就可以不用声明生命周期。

  1. 每一个引用参数都有自己的一个生命周期。
  2. 如果只有一个输入生命周期参数,那么它被赋予所有输出生命周期参数。
  3. 多个输入生命周期参数,&self&mult self,self 的生命周期被赋给所有输出生命周期参数。
  • the dangling reference
    • 未标注的引用