链接 self 的生命周期和方法中的引用 [英] Linking the lifetimes of self and a reference in method

查看:49
本文介绍了链接 self 的生命周期和方法中的引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这段代码:

#[派生(调试)]struct Foo<'a>{x: &'a i32,}impl'a>福'a>{fn set(&mut self, r: &'a i32) {self.x = r;}}fn 主(){让 v = 5;让 w = 7;让 mut f = Foo { x: &v };println!("f 是 {:?}", f);f.set(&w);println!("现在 f 是 {:?}", f);}

我的理解是,在第一次借用v的值时,struct声明上的泛型生命周期参数'a填充的是值的生命周期v.这意味着生成的 Foo 对象的存活时间不得超过此 'a 生命周期,或者 v 的值必须至少存活Foo 对象.

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

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

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

导致以下错误:

error[E0502]: 不能借用 `f` 作为不可变的,因为它也被借用为可变的-->src/main.rs:21:31|19 |f.set(&w);|- 此处发生可变借用20 |21 |println!("现在 f 是 {:?}", f);|^ 不可变借用发生在这里22 |}|- 可变借用到此结束

与上面的示例相反,到第二个 println! 时,f 仍然被认为是可变借用的.被调用,因此它不能同时借用为不可变的.

这是怎么来的?

通过不遗漏生命周期注释,编译器为我在第一个示例中为 &mut self 填充了一个注释.这是按照生命周期省略的规则发生的.但是,通过在第二个示例中将其显式设置为 'a,我将 f 的值和 w 的值的生命周期联系起来.

f 是否被认为是以某种方式借用的?

如果是这样,借用的范围是什么?是 min(f 的生命周期,w 的生命周期) -> f 的生命周期吗?

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

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

解决方案

在调用 set 方法时,使用了 impl 块上的生命周期参数,并为 'a 填充了 w 值的生命周期 在方法签名中.

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

在您的情况下,编译器实际上为 'a 选择了一个与 vw 的生命周期兼容的值.如果这是不可能的,它就会失败,例如在这个例子中:

fn main() {让 v = 5;让 mut f = Foo { x: &v };println!("f 是 {:?}", f);让 w = 7;f.set(&w);println!("现在 f 是 {:?}", f);}

输出:

error[E0597]: `w` 的寿命不够长-->src/main.rs:21:1|18 |f.set(&w);|- 借用发生在这里...21 |}|^ `w` 在借来的时候掉到这里|= 注意:作用域中的值以它们创建的相反顺序删除

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

在第二个示例中,通过强制 self 的生命周期也为 'a,您将可变借用绑定到生命周期 'a 也是如此,因此当生命周期 'a 的所有项目都超出范围时,即 vw,借用结束.

I have this piece of code:

#[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);
}

My understanding is that in the first borrow of the value of v, the generic lifetime parameter 'a on the struct declaration is filled in with the lifetime of the value of v. This means that the resulting Foo object must not live longer than this 'a lifetime or that the value of v must live at least as long as the Foo object.

In the call to the method set, the lifetime parameter on the impl block is used and the lifetime of the value of w is filled in for 'a in the method signature. &mut self is assigned a different lifetime by the compiler, which is the lifetime of f (the Foo object). If I switched the order of the bindings of w and f in the main function, this would result in an error.

I wondered what would happen if I annotated the &mut self reference with the same lifetime parameter 'a as r in the set method:

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

Which results in the following error:

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

In contrast to the example above, f is still considered mutably borrowed by the time the second println! is called, so it cannot be borrowed simultaneously as immutable.

How did this come to be?

By not leaving off the lifetime annotation the compiler filled one in for me for &mut self in the first example. This happens by the rules of lifetime elision. However by explicitly setting it to 'a in the second example I linked the lifetimes of the value of f and the value of w.

Is f considered borrowed by itself somehow?

And if so, what is the scope of the borrow? Is it min(lifetime of f, lifetime of w) -> lifetime of f?

I assume I haven't fully understood the &mut self reference in the function call yet. I mean, the function returns, but f is still considered to be borrowed.

I am trying to fully understand lifetimes. I am primarily looking for corrective feedback on my understanding of the concepts. I am grateful for every bit of advice and further clarification.

解决方案

In the call to the method set the lifetime parameter on the impl block is used and the lifetime of the value of w is filled in for 'a in the method signature.

No. The value of the lifetime parameter 'a is fixed at the creation of the Foo struct, and will never change as it is part of its type.

In your case, the compiler actually choses for 'a a value that is compatible with both the lifetimes of v and w. If that was not possible, it would fail, such as in this example:

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);
}

which outputs:

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

Exactly because the 'a lifetime imposed by v is not compatible with the shorter lifetime of w.

In the second example, by forcing the lifetime of self to be 'a as well, you are tying the mutable borrow to the lifetime 'a as well, and thus the borrow ends when all items of lifetime 'a goes out of scope, namely v and w.

这篇关于链接 self 的生命周期和方法中的引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆