当前位置 : 主页 > 手机开发 > 无线 >

reference – 多个生命周期和移动:借用`x`的赋值发生在这里

来源:互联网 收集:自由互联 发布时间:2021-06-10
我有一个带有函数next()的结构(类似于迭代器但不是迭代器).此方法返回修改后的下一个状态(保留原始状态).所以:fn next( A) – 一个. 我从一个简单的结构开始,我不需要生命周期(示例中
我有一个带有函数next()的结构(类似于迭代器但不是迭代器).此方法返回修改后的下一个状态(保留原始状态).所以:fn next(& A) – >一个.

我从一个简单的结构开始,我不需要生命周期(示例中的结构A),我扩展它以添加对新结构(结构B)的引用.

问题是我现在需要指定我的struct的生命周期,由于某种原因我的方法next()拒绝再工作了.

我怀疑每次迭代的新结构的生命周期都限于创建它的范围,我不能将它移到这个范围之外.

是否可以保留next()方法的行为?

Try it here

#[derive(Clone)]
struct A(u32);
#[derive(Clone)]
struct B<'a>(u32, &'a u32);

impl A {
    fn next(&self) -> A {
        let mut new = self.clone();
        new.0 = new.0 + 1;
        new
    }
}

impl<'a> B<'a> {
    fn next(&self) -> B {
        let mut new = self.clone();
        new.0 = new.0 + 1;
        new
    }
}

fn main() {
    let mut a = A(0);
    for _ in 0..5 {
        a = a.next();
    }

    let x = 0;
    let mut b = B(0, &x);
    for _ in 0..5 {
        b = b.next();
    }
}

错误是:

error[E0506]: cannot assign to `b` because it is borrowed
  --> src/main.rs:31:9
   |
31 |         b = b.next();
   |         ^^^^-^^^^^^^
   |         |   |
   |         |   borrow of `b` occurs here
   |         assignment to borrowed `b` occurs here
问题出在这里:

impl<'a> B<'a> {
    fn next(&self) -> B {
        let mut new = self.clone();
        new.0 = new.0 + 1;
        new
    }
}

您没有为B指定生命周期,即下一步的返回类型.由于Rust的lifetime elision rules,编译器推断你打算这样做:

impl<'a> B<'a> {
    fn next<'c>(&'c self) -> B<'c> {
        let mut new = self.clone();
        new.0 = new.0 + 1;
        new
    }
}

这意味着返回值可能不会超过自我.或者换句话说,自我必须比返回的B长寿.鉴于函数的主体,这是一个完全不必要的要求,因为这些引用是相互独立的.这会导致一个问题:

for _ in 0..5 {
    b = b.next();
}

您正在覆盖借用检查器认为仍然通过调用next()借用的值.接下来我们知道没有这样的关系 – 终身注释并不反映你实际做的事情的限制.

那么这里的生命界限是什么?

>对B的引用的生命期是无关的 – 每个都可以不存在另一个.因此,为了给调用者提供最大的灵活性,B的生命周期应该与下一个自我引用的生命周期不同.
>但是,使用next()创建的每个B都包含对self所持有的相同u32的引用.因此,您为每个B提供的生命周期参数必须相同.

使用明确命名的生命周期,这是结合这两件事的结果:

impl<'a> B<'a> {
    fn next<'c>(&'c self) -> B<'a> {
        let mut new = self.clone();
        new.0 = new.0 + 1;
        new
    }
}

注意 – 即使这里对self的引用具有生命周期’c – self的类型是B<'a>,其中’a是& u32里面的生命周期.与返回值一样.

但实际上,’c可以省略.所以它真的和这个一样:

impl<'a> B<'a> {
    fn next(&self) -> B<'a> {
        let mut new = self.clone();
        new.0 = new.0 + 1;
        new
    }
}
网友评论