考虑以下程序:

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)          //  |     |
}
aStringb&mut Stringc&str。这三个变量都是值,但是bc也是引用。在这种情况下,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);         //  |         |
}

也可以看看:
  • Why does linking lifetimes matter only with mutable references?
  • How can this instance seemingly outlive its own parameter lifetime?
  • Mutable borrow in a getter not living long enough
  • Reference does not live long enough in nested structure
  • Cannot borrow as mutable more than once at a time in one code - but can in another very similar
  • What is the difference between '&self' and '&'a self'?
  • 关于rust - 通用生命周期是作为引用生命周期或引用值的生命周期实现吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57456244/

    10-10 18:34