2.9.1 dyn Trait 生命周期与 Box

译文 · 基于 Learning Rust

dyn Trait 生命周期与 Box

原文链接: https://quinedot.github.io/rust-learning/pf-dyn.html

每个 trait 对象(dyn Trait)都有一个可省略的生命周期,完全省略时有自己的默认值。这个默认值比普通的函数签名省略规则更强。最常见因此遇到生命周期错误的情况是在函数签名、结构体和类型别名中使用 Box<dyn Trait>,它意味着 Box<dyn Trait + 'static>。

错误通常表明在该上下文中不允许非 'static 的引用/类型,但有时意味着你应该添加显式生命周期,如 Box<dyn Trait + 'a> 或 Box<dyn Trait + '_>。

后者将像"普通"生命周期省略一样工作;例如,它会作为函数输入参数引入新的匿名生命周期参数,或在返回位置使用 &self 的生命周期。

生命周期存在的原因是,将值强制转换为 dyn Trait 会擦除其基础类型,包括它可能包含的任何生命周期。但这些生命周期必须以某种方式被编译器跟踪以确保内存安全。dyn Trait 生命周期表示擦除类型有效的上限。


一些简短示例:

1
2
3
4
5
6
7
8
trait Trait {}

// 返回类型是 `Box<dyn Trait + 'static>`,这里会报错,因为
// 需要要求 `T` 为 `'static` 的约束,或者返回
// 类型需要更灵活。
fn one<T: Trait>(t: T) -> Box<dyn Trait> {
    Box::new(t)
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# trait Trait {}
// 添加了约束后可以工作。
fn two<T: Trait + 'static>(t: T) -> Box<dyn Trait> {
    Box::new(t)
}

// 使返回类型更灵活后可以工作。
// (我们仍然必须添加生命周期约束。)
fn three<'a, T: Trait + 'a>(t: T) -> Box<dyn Trait + 'a> {
    Box::new(t)
}

要更深入地探索, 请参阅 dyn Trait 导览的这一节。

最后修改 August 23, 2026: 更新 (499855b16)