修正后的示例:
fn main() {
let strA = "a".to_string();
let result;
{
let strB = "abc".to_string();
result = longest(&strA, &strB);
}
println!("The longest string is {}", result);
}
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}
现在会像预期的那样产生编译器错误:
error[E0597]: `strB` does not live long enough
--> src/main.rs:7:33
|
7 | result = longest(&strA, &strB); // Will return strB
| ^^^^^ borrowed value does not live long enough
8 | }
| - `strB` dropped here while still borrowed
9 |
10 | println!("The longest string is {}", result); // result now point to strB!!
| ------ borrow later used here
Playground
在你的初始示例中,Rust 并没有“忽略”字符串变量的生命周期。当你将一个变量设置为字符串字面量时,该字面量被硬编码到可执行二进制文件中,并获得 'static
生命周期,这意味着它在程序的整个运行期间都是有效的。如果我们给你的初始示例添加显式类型注释,就可以清楚地看到为什么它能够通过编译并正常工作:
fn main() {
let strA: &'static str = "a";
let result;
{
let strB: &'static str = "abc";
result = longest(&strA, &strB);
}
println!("The longest string is {}", result);
}
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}
然而当我们在字符串字面量上调用to_string()
时,我们创建了一个拥有所有权且堆分配的String
,它的生命周期是非静态的,并被限定在所在的块内,因此对代码进行更改会使程序不再按预期编译。