验证Rust生命周期理解:自定义简化示例为何可正常编译?
现象解释
你遇到的差异本质是两种不同来源的&str引用的生命周期规则不同:
- 第一个无法编译的示例中,
string2是String类型,它的堆上存储的字符串内容会随string2离开内部作用域被自动释放,调用longest时传入的string2.as_str()引用的生命周期和string2严格绑定。根据你给longest标注的生命周期规则,返回值的生命周期等于两个入参生命周期中更短的那一个,也就是string2的生命周期,因此result持有该引用时,离开内部作用域后再访问就属于悬垂引用,编译器会直接拦截。 - 你写的测试用例能正常编译,核心是用到了字符串字面量的
'static生命周期特性:
- 代码中
let x = "hello"里的"hello"是字符串字面量,它存储在程序的静态常量区,不会随作用域结束被释放,类型本身就是&'static str,'static标注代表它的有效期覆盖整个程序的运行周期。 - 调用
foo(x)时,编译器会自动推导泛型生命周期'a为'static,因此foo返回的也是&'static str类型的引用。 - 内部作用域结束时,只是栈上的变量
x本身被回收,它指向的静态区的字符串内容依然有效,因此y持有的'static引用完全合法,打印操作不会有任何问题。
你可以做个小验证:把测试用例里的x改为和第一个示例一致的String类型,就会触发你预期的生命周期报错,符合Rust的基础生命周期规则:
fn foo<'a>(x: &'a str) -> &'a str { x } fn main() { let y; { let x = String::from("hello"); y = foo(x.as_str()); } println!("y: {}", y); // 编译报错:`x` does not live long enough }
内容的提问来源于stack exchange,提问作者tarski
相关产品推荐
相关产品推荐

