考虑以下程序:
fn main() {
let c; |<-'a
let mut a = "Hello, world!".to_string(); |
{ |
let b = &mut a; |<-'b |
c = foo(b); | |
} |
println!("{}", c) |
}
fn foo<'z>(a: &'z mut str) -> &'z str {
a
}
b
的生存期为'b
,但是c
的生存期为'a
,比'b
长。 foo
的生存期约束表明foo
的返回值(在这种情况下为c
)与其参数(在这种情况下为b
)具有相同的生存期。 foo
的生命周期约束如何得到满足?
但是,该程序会编译,因此我猜想foo
的生存期参数'z
是b
的参考值(a
)的生存期的真实体现,因此{ {1}}的生命周期约束得到满足吗?
答案 0 :(得分:2)
值具有其自身的生存期,但是引用也跟踪其引用的事物的生存期。不幸的是,这里缺少官方术语。我(和其他一些人)已经开始使用的术语是具体寿命。主要变量有三个,因此有三个具体寿命:
fn main() {
let c; // 'c
let mut a = String::new(); // 'a ¦
{ // | ¦
let b = &mut a; // | 'b ¦
c = foo(b); // | | |
} // | |
println!("{}", c) // | |
}
a
是String
,b
是&mut String
,而c
是&str
。这三个变量都是值,但是b
和c
也是也是引用。在这种情况下,b
是指a
中的值,并且是&'a mut String
。由于c
源自b
,因此它具有相同的“内部寿命”:&'a str
。
值得注意的是,b
本身的生存期从不发挥作用。它非常罕见,因为您需要可变的借贷和“额外的”借贷:
fn main() {
let c;
let mut a = String::new();
{
let mut b = &mut a;
c = foo(&mut b); // Mutably borrowing `b` here
}
println!("{}", c)
}
error[E0597]: `b` does not live long enough
--> src/main.rs:6:17
|
6 | c = foo(&mut b);
| ^^^^^^ borrowed value does not live long enough
7 | }
| - `b` dropped here while still borrowed
8 | println!("{}", c)
| - borrow later used here
在这种情况下,传递给foo
的值的类型为&'b mut &'a mut String
,其值被强制下调为&'b mut str
。值b
的寿命不足,就会出现错误。
我认为该模型无法解释更复杂的借贷关系。例如,如果在
a
之后再次使用println!
,则可变借项不能在a
的整个生命周期中使用
a
的可变借项由c
持有,但是借用的持续时间不需要与c
的生存期相对应。由于non-lexical lifetimes(在此情况下称为“非词汇借用”),由a
持有的c
的借用可以在println!
之后但在范围。
从上方增强该图以显示值的寿命以及括号中引用的值的寿命:
fn main() {
let c; // 'c
let mut a = String::new(); // 'a ¦
{ // | ¦
let b = &mut a; // | 'b('a) ¦
c = foo(b); // | |('a) |('a)
} // | |('a)
println!("{}", c); // | |('a)
// | |
println!("{}", a); // | |
}
另请参阅: