【问题标题】:How does lifetime rule stops multiple mutable borrow?生命周期规则如何阻止多个可变借用?
【发布时间】:2019-08-23 04:47:20
【问题描述】:

我一直在阅读这个issue,它展示了一个简单的示例,说明多个可变借用如何引发此错误"cannot borrow point as mutable more than once at a time"

struct Point {
    x: f64,
    y: f64
}

impl Point {
    pub fn x_mut(&mut self) -> &mut f64 {
        &mut self.x
    }

    pub fn y_mut(&mut self) -> &mut f64 {
        &mut self.y
    }
}

fn main() {
    let mut point = Point { x: 1.0, y: 2.0 };
    let x_mut = point.x_mut();
    let y_mut = point.y_mut();

    *x_mut *= 2.0;
    *y_mut *= 2.0;
} 

但后来让我感到困惑的部分来了。

生命周期省略规则很清楚为什么会发生这种情况: x_mut() 返回一个可变借用,它必须至少存在 self的可变借用

可变借用只要self 就应该存在这一事实如何解释此错误?

【问题讨论】:

  • 变量 x_mut 必须退出作用域(较旧的 Rust)或停止使用(较新的非词法生命周期 Rust)才能完成对 point 的可变借用。只要一个可变借位处于活动状态,就无法建立第二个(变量y_mut 的点)。方法签名说&mut self,但在main 的上下文中,self 指的是point

标签: rust


【解决方案1】:

变量x_mut 必须退出作用域(较旧的 Rust)或停止使用(较新的非词法生命周期 Rust)才能完成对 point 的可变借用。只要一个可变借位处于活动状态,就无法建立第二个借位(变量y_mut 的点)。方法签名说&mut self,但在main 的上下文中,self 指的是point

         |
 +->  18 |     let x_mut = point.x_mut();
 |       |                 ----- first mutable borrow occurs here
 |    19 |     let y_mut = point.y_mut();
 |       |                 ^^^^^ second mutable borrow occurs here
 |    20 | 
 +->  21 |     *x_mut *= 2.0;
         |     ------------- first borrow later used here

第一次借用的范围是从 18 到 21,并且,您不能在该范围内有另一个可变借用 point。所以 19 被标记为错误。第 19 行的代码可以愉快地出现在第 21 行之后,因此以下是合法的:

fn main() {
    let mut point = Point { x: 1.0, y: 2.0 };

    let x_mut = point.x_mut();
    *x_mut *= 2.0;

    let y_mut = point.y_mut();
    *y_mut *= 2.0;
} 

【讨论】:

  • 对不相交字段的两个可变引用可以共存。这就是他在这方面想要达到的目标。但我不明白的是,self 的生命周期与他的建议以及这个问题的模拟解决方案有什么关系。
  • 您询问的代码告诉借用检查器您要对point 进行可变借用,以便.x_mut() 的可变借用返回值可以与@ 中的代码一样长987654334@ 需要它。因此,point.x_mut() 的调用建立了对point 的借用,只要返回结果存在,编译器就会持续存在。由于借用的返回结果存在一段时间,所以point 的可变借用也被认为可以存在那么久。因此,在第一次此类借用的窗口内,不可能对point.y_mut() 的调用进行第二次可变借用。
  • 至于不相交字段的重叠借用,这是可能的,也是一个很好的问题:直接做很容易,但是封装成方法使它变得棘手;建议您(搜索和/或)在单独的问题中直接询问。例如,请参阅here,其中我们可变地借用 x 和 y,但在一个方法中,它仅使用 point 的一个可变借用。
【解决方案2】:

我认为您的直觉是正确的,因为生命周期省略规则并没有真正解释这一点。部分问题是该示例包含一些红鲱鱼。例如,您可以注释掉:

*y_mut *= 2.0;

仍然得到错误。此外,您不需要实际使用 x_mut 作为 mutable 来获取错误。这个更简单的版本说明了同样的问题:

fn main() {
    let mut point = Point { x: 1.0, y: 2.0 };
    let x_mut = point.x_mut();
    let y_mut = point.y_mut();

    println!("x_mut = {}", x_mut);
}

如果您注释掉 y_mut 行,或者即使您在调用 println!() 之后移动该行,它也可以正常工作。所以就像你一开始说的,你不能同时有多个对point的可变引用。

请注意,我仅指您的帖子,而不是您链接到的我尚未阅读的讨论。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-11-29
    • 2016-12-22
    • 2020-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-15
    相关资源
    最近更新 更多