Rust 生命周期

生命周期标注如何描述引用之间的存活关系;省略规则与函数签名中的常见模式。

#type / concept #status / growing #tech / dev #resource / rust

[!info] 关联笔记

Rust 生命周期

这个概念为什么出现

引用不能比它指向的数据活得更久。多数时候编译器能推断;当函数有多个引用输入/输出时,需要你用生命周期标注说明输出借自哪路输入

[!abstract] 一句话理解 生命周期是引用有效的作用域参数;'a 不创造生命,只描述借用关系,帮助编译器证明返回的引用不会悬垂。

最小可运行示例

场景:广告文案——返回两个候选里较长的借用

运营配置两个 slogan,函数返回较长者的 &str 视图,避免分配新 String

// 业务意图:在两个 slogan 中返回较长的借用。
// 教学点:显式 'a 说明返回引用与两个输入中的借用关系。

fn longer<'a>(a: &'a str, b: &'a str) -> &'a str {
    if a.len() >= b.len() { a } else { b }
}

fn main() {
    let s1 = String::from("flash-sale");
    let s2 = String::from("vip-only-weekend");
    let pick = longer(&s1, &s2);
    println!("pick={pick}");
}

建议运行:cargo run

期望输出:

pick=vip-only-weekend

结合场景再看三个关注点

  1. 返回值生命周期不能长于任一可能来源(此签名要求两者同一 'a 约束下的交集语义)
  2. 标注是契约,写错会编译失败或过度限制
  3. 不需要标注局部变量的“内部推断” 时保持简洁

核心概念与准确模型

标注位置

fn f<'a>(x: &'a str) -> &'a str { x }

省略规则(直觉)

编译器对许多简单签名自动填充生命周期;多输入且返回引用时常需手写。

不是“延迟 drop 的魔法”

生命周期不改变运行时 drop 时机;它是静态证明。

结构体字段引用

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

结构体不能比其字段借用活得更久,见 进阶

设计动机

  • 零运行时开销的悬垂引用防护
  • 让 API 明确“数据从哪来”
  • 与泛型同一套参数语法

边界与误区

  • 'static 不是“最好”,它意味着可存活整个程序(字面量等)
  • 生命周期纠缠难读时,优先改为拥有型数据
  • 与异步/自引用结构体是高级坑

[!warning] 常见误区:觉得加 'a 能修好任何借用错误 标注只描述关系;所有权/作用域设计错误无法靠记号掩盖。

工程实践

  1. 先尝试改签名为拥有型返回 String
  2. 热路径零拷贝再引入引用与 'a
  3. 公共 API 生命周期写清楚并文档化
  4. 复杂时拆函数降低标注难度

本节总结

  • 生命周期描述借用关系
  • 返回引用必须锚定输入
  • 能拥有就简单,需借用再标注

自测题

  1. 生命周期参数是否影响运行时?
  2. 何时应该返回 String 而不是 &str
参考答案
  1. 否,主要是编译期检查。
  2. 需要独立所有权、拼接新数据、或借用关系说不清时。

延伸阅读与资料来源

资料类型支撑内容
The Book — Validating References with Lifetimes官方书生命周期
Rust Reference — Lifetime elision规范省略规则
创建于 2026/7/15 更新于 2026/7/15