在迭代器中将变量作为可变引用借出后,在循环中以不可变方式借出

4

我想从循环内部的方法中获取返回值,但是迭代器也被作为可变引用借用了。而方法需要一个不可变引用。

这是一个小的可复现代码 (playground链接):

struct Foo {
    numbers: Vec<u8>,
    constant: u8
}

impl Foo {
    pub fn new()-> Foo {
        Foo {
            numbers: vec!(1,2,3,4),
            constant: 1
        }
    }

    pub fn get_mut(&mut self){
        for mut nmb in self.numbers.iter_mut() {
            {
                let constant = self.get_const();
            }
        }
    }

    pub fn get_const(&self)-> u8 {
        self.constant
    }
}

fn main() {
    let mut foo = Foo::new();

    foo.get_mut();
}

我遇到了如下错误:

error[E0502]: cannot borrow `*self` as immutable because it is also borrowed as mutable
  --> src/main.rs:17:32
   |
15 |         for  nmb in self.numbers.iter_mut() {
   |                     -----------------------
   |                     |
   |                     mutable borrow occurs here
   |                     mutable borrow later used here
16 |             {
17 |                 let constant = self.get_const();
   |                                ^^^^ immutable borrow occurs here

2
这只是一个例子,或者在你的情况下做 let constant = self.constant; 是否可以? - loganfsmyth
2
如果get_const返回的值在循环执行期间保持不变,您也可以将其存储在循环外的变量中。 - EvilTak
1
@EvilTak 返回 get_const 的值依赖于 numbers 向量的当前状态。在此示例中,我仅使用了 u8。在我的用例中,这应该是一个结构体。 - Ramesh Kithsiri HettiArachchi
你需要整个“numbers”数据集还是其中的一部分?这将影响其相关性。顺便问一下,你的循环是否实际上通过改变“numbers”来进行变异?如果是这样,那么你只需要处理当前正在处理的数字之前的“numbers”吗? - loganfsmyth
2
你可能需要对numbers进行索引,而不是使用迭代器。这样,您可以将可变借用的生命周期缩小到实际更改值的代码部分(playground)。 - Jmb
显示剩余2条评论
1个回答

2
如果 self.get_const() 不依赖于 self.numbers,你可以在循环外计算它:
let constant = self.get_const();
for mut nmb in self.numbers.iter_mut() {
    // ...
}

或者直接访问该字段:
for mut nmb in self.numbers.iter_mut() {
    let constant = self.constant;
}

如果它取决于self.numbers,您需要使用索引。确保在索引之前计算常量。
for i in 0..self.numbers.len() {
    let constant = self.get_const();
    let nmb = &mut self.numbers[i];
}

你还需要确保不插入或删除任何值,因为这可能会导致索引中出现错误。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接