可变借用不止一次 [英] Mutable borrow more than once

查看:39
本文介绍了可变借用不止一次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个无法编译的简短示例的简短示例.错误在 add1 函数中.如果我在 add2 中这样做,它会起作用,但这不是很 DRY.有更多经验的人能告诉我如何以比 add2 更好的方式克服可变借用多次错误.

This is a short sample of short example that doesn't compile. The error is in the add1 function. It works if I do as in add2, but this isn't very DRY. Can someone with more experience enlighten me of how to overcome the mutable borrow more than once error in a better way than in add2.

struct S1 {
    full: bool,
    v: Vec<u32>,
}

struct S2 {
    v: Vec<S1>,
}

impl S2 {
    // If last is not full push n to last.v, otherwise push a new S1

    // Doesn't work
    fn add1(&mut self, n: u32) {
        // Let's assume it's not empty
        let s1 = self.v.last_mut().unwrap();
        if !s1.full {
            s1.v.push(n);
        } else {
            self.v.push(S1 {
                full: false,
                v: vec![n],
            });
        }
    }

    // Works
    fn add2(&mut self, n: u32) {
        // First getting last as immutable ref and then as mutable ref
        let full = self.v.last().unwrap().full;
        if !full {
            self.v.last_mut().unwrap().v.push(n);
        } else {
            self.v.push(S1 {
                full: false,
                v: vec![n],
            });
        }
    }
}

fn main() {}

游乐场

编译器错误:

error[E0499]: cannot borrow `self.v` as mutable more than once at a time
  --> src/main.rs:20:13
   |
16 |         let s1 = self.v.last_mut().unwrap();
   |                  ------ first mutable borrow occurs here
...
20 |             self.v.push(S1 {
   |             ^^^^^^ second mutable borrow occurs here
...
25 |     }
   |     - first borrow ends here

推荐答案

您有两个选择.

1) 每晚使用并将 #![feature(nll​​)] 放在文件顶部.

1) Use nightly and put #![feature(nll)] at the top of your file.

非词法生命周期正好解决了这个问题:即使在 else 块中没有使用 s1 借用,它仍然存在并阻止 self.v 的突变.使用非词法生命周期,编译器会识别 s1 实际上已死并让您再次借用.

Non-lexical lifetimes solve exactly this issue: even though the s1 borrow is not used in the else block, it's still alive and blocking mutation of self.v. With non-lexical lifetimes, the compiler recognizes that s1 is effectively dead and lets you borrow again.

2) 像这样构造你的代码:

2) Structure your code like this:

fn add1(&mut self, n: u32) {
    { // add a scope around s1 so that it disappears later
        let s1 = self.v.last_mut().unwrap();
        if !s1.full {
            s1.v.push(n);
            return; // just return early instead of using else
        }
    }
    self.v.push(S1 {
        full: false,
        v: vec![n]
    });
}

这篇关于可变借用不止一次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆