考虑以下程序:
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
)的生存期实现,从而满足foo
的生存期约束? 最佳答案
值具有其自己的生存期,但是引用也跟踪其引用的事物的生存期。不幸的是,这里缺少官方术语。我(和其他一些人)开始使用的术语是具体生命周期。 main中有三个变量,因此有三个具体的生存期:
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
保留了可变的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); // | |
}
也可以看看:
关于rust - 通用生命周期是作为引用生命周期或引用值的生命周期实现吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57456244/