---
title: 生命周期
url: https://doc.liz6.com/rust/01-ownership-and-borrowing/03-lifetime
locale: zh
area: rust
tags:
- rust
- 所有权与借用
date: 2026-06-30
modified: 2026-06-30
description: 生命周期('a)不是运行时的值——它是编译期对引用有效作用域的约束。从 elision 规则(编译器自动推导)到显式标注(struct/variance/HRTB),生命周期标注本质上是在告诉借用检查器"这几个引用之间谁活得比谁长"。
---

# 生命周期

> 生命周期(`'a`)不是运行时的值——它是编译期对引用有效作用域的约束。从 elision 规则(编译器自动推导)到显式标注(struct/variance/HRTB),生命周期标注本质上是在告诉借用检查器"这几个引用之间谁活得比谁长"。

## Lifetime 是编译期概念

Lifetime 参数（`'a`）不是运行时的值——它们只是编译期的**约束**：这个引用的有效作用域不能比 `'a` 更长。编译器在 MIR 上用 region inference 推导最小 lifetime。

## Lifetime Elision

大多数函数不需要显式标注 lifetime——编译器根据 3 条规则自动推导：

1. 每个不标注 lifetime 的引用参数被分配独立的 lifetime（`fn foo<'a, 'b>(x: &'a T, y: &'b U)`）
2. 如果只有一个 input lifetime，它被赋给所有 output lifetime（`fn foo<'a>(x: &'a T) -> &'a U`）
3. 如果多个 input lifetime 中有 `&self` 或 `&mut self`，`self` 的 lifetime 赋给所有 output

规则 2 是最常见的：单个引用参数 → 返回的引用默认借用该参数。规则 3 是 why method chaining works：`self` 的 borrow 传递到返回值。

## Struct 中的 Lifetime

当 struct 包含引用时，必须显式标注 lifetime：

```rust
struct Excerpt<'a> {
    part: &'a str,                   // 这个引用不能比 'a 活得更久
}

impl<'a> Excerpt<'a> {
    fn announce(&self, msg: &str) -> &str {  // rule 3: output borrows self
        println!("{}", msg);
        self.part
    }
}
```

编译器的保证：`Excerpt<'a>` 实例不能活得比被引用的 `&'a str` 更久。

## 'static

`'static` 是唯一有"特殊"含义的 lifetime——它表示引用的数据存活于整个程序生命周期。来源：

- 字符串字面量：`"hello"` 的类型是 `&'static str`——编译期嵌入二进制，始终有效
- `Box::leak(Box::new(T))` 可以制造 `&'static mut T`
- `static` 变量和 `const` 引用

## Variance

Rust 的 lifetime 有 **subtyping variance**。理解它的关键规则：

- `'long: 'short`（即 `'long` 活得比 `'short` 长，所以 `'long` 满足 `'short` 的约束）
- `&'a T`: covariant in `'a`（如果 `'long: 'short`，则 `&'long T` 可用于 `&'short T`）
- `&'a mut T`: invariant in `'a`（不能缩短可变引用的 lifetime——否则可能违反 aliasing XOR mutation）

```rust
fn assign<T>(to: &mut T, from: T) { *to = from; }

let mut x: &'static str = "hello";
{
    let y = String::from("world");
    // assign(&mut x, y.as_str());   // ERROR: T = &'static str (from to), but y is &'y str
}
// 如果这能编译, x 指向 y 的数据 → y 被 drop → 悬垂指针
```

## HRTB (Higher-Ranked Trait Bounds)

当 closure 参数有 lifetime 但不需要显式声明时：

```rust
fn apply<F>(f: F) where F: for<'a> Fn(&'a str) -> &'a str { ... }
// "f 对于**任意** lifetime 'a 都满足 Fn(&'a str) -> &'a str"
// 不需要 caller 处指定 'a — 编译器自动量化
```

## PhantomData

当 struct 有 lifetime 但没有直接存储引用——用 `PhantomData` 标记所有权/借用关系：

```rust
use std::marker::PhantomData;

struct MyIter<'a, T> {
    ptr: *const T,                   // 裸指针 — 不携带 Rust 的借用关系!
    _marker: PhantomData<&'a T>,     // 告诉编译器: "这个 struct 逻辑上持有 &'a T"
}
```

## 参考

- **Rust Book**: Chapter 10.3 — Validating References with Lifetimes
- **Rust Reference**: lifetime elision, variance
- **RFC**: RFC 2094 (NLL), RFC 387 (Higher-Ranked Trait Bounds)

*Keywords: lifetime, elision, 'static, variance, covariant, invariant, HRTB, PhantomData, region inference*
