【问题标题】:Struct methods: Cannot borrow as mutable because it is also borrowed as immutable结构方法:不能借用为可变的,因为它也被借用为不可变的
【发布时间】:2020-09-25 19:07:51
【问题描述】:

我有以下代码(只是一个例子)不能满足借用检查器。 一种方法修改struct 的一个字段并调用另一种方法来修改另一个。问题是在调用第二种方法时,它需要一个依赖于结构的参数。对 second 方法的调用不适用于参数 &self.a&mut self.a,因为这将是第二个可变借用。

最后,我将所有代码都用一种方法解决了,但这太难看了(在我的真正问题中)。 如何解决? (我知道参数&self.a 不是必需的,但这不是我要说明的重点……)


struct ABC {
    a: Vec<i32>,    // no Copy trait
    b: i32,
}

impl ABC {
    fn new() -> ABC { ABC {a: vec![0,1], b: 10} }

    fn first(&mut self) {
        self.a.push(2);         // updates one field
        self.second(&self.a);   // uses a method to update the other field
    }

    fn second(&mut self, x: &Vec<i32>) {
        self.b += x[1];
    }
}

fn main() {
    let mut s = ABC::new();
    s.first();
}

Playground here.

【问题讨论】:

  • 如果您只想封装该部分,可以将其设为辅助函数fn second(y: &amp;mut i32, x: &amp;Vec&lt;i32&gt;)

标签: rust borrow-checker


【解决方案1】:

你已经从 self.a 借了;因此,只要存在借位,您就无法使用第二种方法。您可以使用to_vec()将数据复制到第二种方法。

struct ABC {
    a: Vec<i32>,    // no Copy trait
    b: i32,
}

impl ABC {
    fn new() -> ABC { ABC {a: vec![0,1], b: 10} }

    fn first(&mut self) {
        self.a.push(2);         // updates one field
        self.second(self.a.to_vec());
    }

    fn second(&mut self, x: Vec<i32>) {
        self.b += x[1];
    }
}

fn main() {
    let mut s = ABC::new();
    s.first();
}

playground

但如前所述,它会复制数据。

最简单的方法是在first 方法中更新self.b。这样我们就不会向self.a借两次了

    fn first(&mut self) {
        self.a.push(2);         // updates one field
        self.b += self.a[1];
    }

如果 second 没有从 self 借用,它将按如下方式工作:

struct ABC {
    a: Vec<i32>, // no Copy trait
    b: i32,
}

impl ABC {
    fn new() -> ABC {
        ABC {
            a: vec![0, 1],
            b: 10,
        }
    }

    fn first(&mut self) {
        self.a.push(2); // updates one field
        Self::second(&mut self.b, &self.a);
    }
    fn second(y: &mut i32, x: &Vec<i32>) {
        *y += x[1];
    }
}

fn main() {
    let mut s = ABC::new();
    s.first();
}

但是和直接在first方法中更新self.b差别不大。

【讨论】:

  • 但是to_vec() 会进行克隆,对于大型向量来说效率低下。我只想要一个参考,以便从向量中读取一些值而不改变它们。
  • 那么为什么不在first方法中更新向量呢?
  • 您不必从 impl ABC 块中删除 second 以使其在没有 self 参数的情况下工作;您只需将其称为Self::second(...)。 (如果 second 仅在 first 内部使用,我会认真考虑将其 inside first 以限制其范围,但这可能部分违背了首先将其分解的目的.)
  • @trentcl 是的,我最终将second 移动到first 中,正如问题中所说,但只是想知道如何解决这个问题。 Self::second(...) 做到了,谢谢。我会接受这个更新的答案。谢谢@edkeveked。
猜你喜欢
  • 2018-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多