Rust中str与String的生命周期疑问:两段代码编译结果为何不同?
字符串字面量与String的生命周期差异解析
先看你给出的第一个报错案例:
fn check_check() { let r; { let s = String::from("s"); r = check(&s); // 报错:s does not live long enough } println!("{}", r); } fn check<'a>(s: &'a str) -> &'a str { return s; }
这里的s是String类型,它的堆内存由栈上的s变量持有所有权。当内部代码块结束,s被销毁,对应的堆内存也会被释放。r拿到的引用指向的是已经被回收的内存,编译器自然会报错阻止这种悬垂引用。
再看第二个能正常编译的案例:
fn check_check() { let r; { let s = "a"; r = check(&s); // 编译正常 } println!("{}", r); } fn check<'a>(s: &'a str) -> &'a str { return s; }
关键区别在于字符串字面量的生命周期是'static。像"a"这种字符串字面量,是直接被嵌入到程序的二进制文件里的,从程序启动到退出,它的内存一直存在。
这里的let s = "a";其实是创建了一个&'static str类型的引用,而不是拥有所有权的String。当你把&s传给check函数时,编译器会把生命周期参数'a推断为'static——因为s本身就是静态生命周期的引用。所以r最终持有的是一个指向静态内存的引用,就算内部代码块结束,这个引用指向的内容依然有效,编译器当然不会报错。
总结两个核心点:
String::from("s")是拥有所有权的动态字符串,生命周期受限于它的定义作用域,作用域结束就会被销毁。- 字符串字面量是
&'static str,生命周期贯穿整个程序运行期,不会随作用域消失而失效。
内容的提问来源于stack exchange,提问作者Karan Kumar
相关产品推荐
相关产品推荐

