Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

English Original

7.1 生命周期与借用深钻 🟢

生命周期 (Lifetimes) 是 Rust 编译器确保所有借用均为有效引用的方式。在 Rust 中,每个引用都有一个 生命周期,即该引用有效的范围。

1. 借用检查器 (Borrow Checker)

借用检查器会比较作用域(Scopes)以确定所有借用是否合法。

fn main() {
    let r;                // ---------+-- 'a
                          //          |
    {                     //          |
        let x = 5;        // --+-- 'b |
        r = &x;           //   |      |
    }                     // --+      |
                          //          |
    // println!("r: {r}"); // ❌ 错误:`x` 的寿命不够长
}                         // ---------+

2. 生命周期省略规则 (Lifetime Elision Rules)

在大多数情况下,你不需要显式编写生命周期标注,因为编译器遵循以下三条确定性规则:

  1. 规则 1:每个是引用的参数都会获得其各自的生命周期参数。
  2. 规则 2:如果恰好只有一个输入生命周期参数,则该生命周期会分配给所有输出生命周期参数。
  3. 规则 3:如果存在多个输入生命周期参数,但其中一个是 &self&mut self,则 self 的生命周期会分配给所有输出生命周期参数。

3. 显式生命周期标注

有时编译器需要你的帮助来理解多个引用之间的关系。标注使用 ' 前缀(例如 'a)。

函数签名

#![allow(unused)]
fn main() {
// 这告诉编译器返回的引用至少与两个输入中寿命较短的那个一样长。
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}
}

结构体定义

如果结构体持有一个引用,则它 必须 显式地为该引用定义生命周期。

struct ImportantExcerpt<'a> {
    part: &'a str,
}

fn main() {
    let novel = String::from("叫我以实玛利。几年前……");
    let first_sentence = novel.split('.').next().expect("找不到 '.'");
    let i = ImportantExcerpt {
        part: first_sentence,
    };
}

4. 'static 生命周期

'static 是一个特殊的生命周期,它贯穿 程序运行的全过程。所有的字符串字面量都具有 'static 生命周期。

#![allow(unused)]
fn main() {
let s: &'static str = "我具有静态生命周期。";
}

对 C/C++ 开发者的总结

  • 在 C/C++ 中:你需要手动跟踪指针的有效性。如果你弄错了,会导致段错误 (Segfault) 或未定义行为 (UB)。
  • 在 Rust 中:你(有时)标注引用之间的关系。如果你弄错了,代码将 无法通过编译