0Pricing
Learn Rust Coding · 课时

结构体中的生命周期

借用字段

结构体中的生命周期 是 CoddyKit 上的免费 Learn Rust Coding 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Learn Rust Coding 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Learn Rust Coding 课程共包含 4 节课。

结构体可以借用数据

大多数结构体都拥有自己的数据。但结构体也可以持有不属于自己的数据的引用。如果这样做,结构体就需要一个生命周期参数。

这能保证结构体的生命周期不会超过被借用数据的生命周期。

在结构体上声明生命周期

在结构体名称后面的尖括号中添加生命周期,然后在引用字段上使用它。这表示结构体的生命周期不能超过该引用的生命周期。

struct Excerpt<'a> {
    text: &'a str,
}

fn main() {
    let novel = String::from("Call me Ishmael. Some years ago...");
    let first = novel.split('.').next().unwrap();
    let e = Excerpt { text: first };
    println!("{}", e.text);
}

它增加的约束

该注解表示,Excerpt 的实例只有在它借用的字符串仍然有效时才有效。无论结构体在何处使用,编译器都会强制执行这一点。

借用结构体上的方法

这类结构体的方法也会在 impl 标头中携带生命周期。通常,得益于生命周期省略,您可以省略方法体中的生命周期(下一课会介绍)。

struct Excerpt<'a> { text: &'a str }

impl<'a> Excerpt<'a> {
    fn announce(&self) -> &str {
        println!("Attention!");
        self.text
    }
}

fn main() {
    let s = String::from("hello world");
    let e = Excerpt { text: &s };
    println!("{}", e.announce());
}

为什么不直接拥有数据?

拥有数据(使用 String)更简单,通常也是首选。借用数据可以避免复制大量数据,对于查看现有缓冲区内容的解析器和视图很有用。

只有在借用确实有好处时,才在结构体中使用生命周期。

解析器视图示例

让结构体持有指向源字符串的切片是一个经典用法。它可以读取原始缓冲区,而无需复制数据。

struct Token<'a> {
    word: &'a str,
}

fn main() {
    let line = String::from("let x = 5");
    let tokens: Vec<Token> = line.split_whitespace().map(|w| Token { word: w }).collect();
    for t in &tokens {
        println!("token: {}", t.word);
    }
}

多个引用字段

结构体可以持有多个引用。根据这些引用的有效性之间的关系,它们可以共享一个生命周期,也可以使用不同的生命周期。

struct Pair<'a> {
    left: &'a str,
    right: &'a str,
}

fn main() {
    let a = String::from("foo");
    let b = String::from("bar");
    let p = Pair { left: &a, right: &b };
    println!("{} {}", p.left, p.right);
}

悬垂结构体错误

如果被借用的数据在结构体仍然存在时被释放,编译器就会拒绝这段代码。生命周期参数正是实现这项检查的关键。

返回借用数据的结构体

用于构建这类结构体的函数,会将结构体的生命周期与其输入相关联。结构体的生命周期不能超过传入数据的生命周期。

struct Wrap<'a> { inner: &'a str }

fn wrap<'a>(s: &'a str) -> Wrap<'a> {
    Wrap { inner: s }
}

fn main() {
    let text = String::from("wrapped");
    let w = wrap(&text);
    println!("{}", w.inner);
}

拥有数据与借用数据的权衡

快速指南:

  • 需要让数据独立保留?请拥有它(String、Vec)。
  • 只需查看现有数据一段较短的时间?请使用生命周期来借用它。

思维模型

带有 'a 的结构体,就像贴在别人笔记本上的便签:只有在那本笔记本仍然存在时,它才有意义。Rust 会确保您不会去读取一本已经不存在的笔记本上的便签。

快速检查

测试您对结构体中生命周期的理解。

回顾

您学会了结构体中的生命周期:

  • 持有引用的结构体需要生命周期参数
  • 生命周期会将结构体的有效性与被借用数据关联起来
  • 方法会在 impl 标头中携带生命周期
  • 除非借用能避免有意义的数据复制,否则优先选择拥有数据

常见问题解答

「结构体中的生命周期」课时是免费的吗?

是的 — 「结构体中的生命周期」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Learn Rust Coding 课程的其余内容,请升级到 CoddyKit PRO。 Learn Rust Coding 课程共包含 4 节课。

「结构体中的生命周期」这节课中我会学到什么?

借用字段 你通过在浏览器中直接运行的动手代码来练习 Learn Rust Coding,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Learn Rust Coding 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Learn Rust Coding 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。

「结构体中的生命周期」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Learn Rust Coding 课中编写并运行代码吗?

能。每节 Learn Rust Coding 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 为什么需要生命周期
  2. 生命周期注解
  3. 结构体中的生命周期
  4. 省略规则
← 返回 Learn Rust Coding