rust 具有生存期和更高引用的可变方法

vlf7wbxs  于 2023-02-12  发布在  其他
关注(0)|答案(1)|浏览(107)

请看下面的代码:

struct Foo<'a> {
    borrowed: &'a u8,
    owned_one: Vec<u8>,
    owned_two: Vec<u8>,
    output: usize
}

impl<'a> Foo<'a> {
    fn do_stuff(&mut self) {
        self.output = self.owned_one.len();
        let zipped = self.owned_one.iter().zip(self.owned_two.iter());
        Self::subroutine(&zipped);
    }
    
    fn subroutine<Arg: Iterator<Item=(&'a u8, &'a u8)>>(_zipped: &Arg) {}
}

fn main() {
    let num = 0u8;
    let mut foo = Foo {
        borrowed: &num,
        owned_one: vec![0],
        owned_two: vec![1],
        output: 0
    };
    foo.do_stuff();
    let _out = &foo.output;
}

playground link
它不会编译,并产生以下错误:

error: lifetime may not live long enough
  --> src/lib.rs:12:9
   |
8  | impl<'a> Foo<'a> {
   |      -- lifetime `'a` defined here
9  |     fn do_stuff(&mut self) {
   |                 - let's call the lifetime of this reference `'1`
...
12 |         Self::subroutine(&zipped);
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'a`

我并不完全理解这个抱怨--self肯定总是有一个生命周期被赋给我们正在使用impl的类吗?--但是我可以理解zip()的两个参数需要持续相同的时间,所以我将do_stuff改为&'a mut self

struct Foo<'a> {
    borrowed: &'a u8,
    owned_one: Vec<u8>,
    owned_two: Vec<u8>,
    output: usize
}

impl<'a> Foo<'a> {
    fn do_stuff(&'a mut self) {
        self.output = self.owned_one.len();
        let zipped = self.owned_one.iter().zip(self.owned_two.iter());
        Self::subroutine(&zipped);
    }
    
    fn subroutine<Arg: Iterator<Item=(&'a u8, &'a u8)>>(_zipped: &Arg) {}
}

fn main() {
    let num = 0u8;
    let mut foo = Foo {
        borrowed: &num,
        owned_one: vec![0],
        owned_two: vec![1],
        output: 0
    };
    foo.do_stuff();
    let _out = &foo.output;
}

但是,现在编译失败,并显示:

error[E0502]: cannot borrow `foo.output` as immutable because it is also borrowed as mutable
  --> src/lib.rs:27:16
   |
26 |     foo.do_stuff();
   |     -------------- mutable borrow occurs here
27 |     let _out = &foo.output;
   |                ^^^^^^^^^^^
   |                |
   |                immutable borrow occurs here
   |                mutable borrow later used here

为什么在do_stuff的参数列表中指定self的生存期意味着我以后突然不能使用foo的不可变引用;我能做些什么呢

wj8zmpe1

wj8zmpe11#

在这里写fn do_stuff(&'a mut self)意味着,这个借用的自我的生命周期,必须和这个自我所借用的一样长,那通常不是你想要的。
你的错误就在这里fn subroutine<Arg: Iterator<Item=(&'a u8, &'a u8)>>(_zipped: &Arg) {}。想想你声明的词汇意义。你的方法除了需要一个“parent”生命周期什么都不返回?没有理由这样做。简单的解决方案就是为你的Item引入一个新的生命周期。就像fn subroutine<'i, Arg: Iterator<Item=(&'i u8, &'i u8)>>(_zipped: &Arg) {}一样。除非你的函数返回一些链接到'a的东西,否则这里不应该有parent的生命周期。
此外,最好接受IntoIterator,因为它更通用,没有理由通过引用接受它,最后,当您有如此复杂的通用时,最好使用where,如果您真的想要学究气,您需要两个生命周期:

fn subroutine<'i, 'j, Arg>(_zipped: Arg)
where
    Arg: IntoIterator<Item = (&'i u8, &'j u8)>,
{
}

相关问题