我有一个带有函数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
}
}
