链接self的生命周期和method中的引用



我有这段代码:

#[derive(Debug)]
struct Foo<'a> {
    x: &'a i32,
}
impl<'a> Foo<'a> {
    fn set(&mut self, r: &'a i32) {
        self.x = r;
    }
}
fn main() {
    let v = 5;
    let w = 7;
    let mut f = Foo { x: &v };
    println!("f is {:?}", f);
    f.set(&w);
    println!("now f is {:?}", f);
}

我的理解是,在第一次借用v的值时,结构声明上的泛型生命周期参数'av的值的生命周期填充。这意味着产生的Foo对象的生存期不能超过'a的生存期,或者v的值必须至少与Foo对象的生存期一样长。

在调用set方法时,使用impl块上的lifetime参数,并在方法签名中为'a填充w值的lifetime。&mut self被编译器分配了一个不同的生命周期,即f (Foo对象)的生命周期。如果我在main函数中交换wf的绑定顺序,这将导致错误。

我想知道如果我在set方法中用与r相同的生命周期参数'a注释&mut self引用会发生什么:

impl<'a> Foo<'a> {
    fn set(&'a mut self, r: &'a i32) {
        self.x = r;
    }
}

将导致以下错误:

error[E0502]: cannot borrow `f` as immutable because it is also borrowed as mutable
  --> src/main.rs:21:31
   |
19 |     f.set(&w);
   |     - mutable borrow occurs here
20 | 
21 |     println!("now f is {:?}", f);
   |                               ^ immutable borrow occurs here
22 | }
   | - mutable borrow ends here

与上面的例子相反,到第二次打印时,f仍然被认为是可变的借用。被调用,因此它不能作为不可变的同时被借用。

这是怎么发生的?

在第一个例子中,编译器没有省略生存期注释,为&mut self填充了一个注释。这是根据终身省略的规则发生的。然而,在第二个例子中,通过显式地将其设置为'a,我将f的值和w的值的生命周期联系起来。

f被认为是自己借来的吗?

如果是,借阅的范围是什么?是min(lifetime of f, lifetime of w) -> lifetime of f ?

我认为我还没有完全理解函数调用中的&mut self引用。我的意思是,函数返回,但f仍然被认为是借来的。

我试图完全理解生命。我主要是在寻找关于我对概念理解的纠正反馈。我很感激你的每一点建议和进一步的澄清。

在调用set方法时,使用impl块上的lifetime参数,并在方法签名中为'a填充w值的lifetime。

。生命周期参数'a的值在Foo结构体创建时是固定的,并且永远不会改变,因为它是其类型的一部分。

在您的例子中,编译器实际上为'a选择了一个与vw的生存期都兼容的值。如果这是不可能的,它将失败,例如在这个例子中:

fn main() {
    let v = 5;
    let mut f = Foo { x: &v };
    println!("f is {:?}", f);
    let w = 7;
    f.set(&w);
    println!("now f is {:?}", f);
}
输出:

error[E0597]: `w` does not live long enough
  --> src/main.rs:21:1
   |
18 |     f.set(&w);
   |            - borrow occurs here
...
21 | }
   | ^ `w` dropped here while still borrowed
   |
   = note: values in a scope are dropped in the opposite order they are created

正是因为v强加给'a的生命周期与w较短的生命周期不兼容。

在第二个例子中,通过将self的生存期也强制为'a,您将可变借用也绑定到'a的生存期,因此当生存期'a的所有项都超出作用域时,即vw,借用结束。

最新更新