有条件地从二进制堆中弹出元素时,借用检查器不满意

Borrow checker is not happy when conditionally popping elements from binary heap

我正在尝试编写一个简单的函数,它会从满足特定条件的 BinaryHeap 中弹出元素。该函数如下所示:

fn check_the_queue(mut queue: BinaryHeap<i32>) {
while !queue.is_empty() {
    let entry = queue.peek().unwrap();
    if *entry <= 0 {
        queue.pop();
    } 
}

编译借用检查器时开始抱怨:

src/main.rs:52:13: 52:18 error: cannot borrow `queue` as mutable because it is also borrowed as immutable

我怎样才能解决这个问题并让借阅检查员满意?

错误消息描述性很强:

<anon>:8:13: 8:18 error: cannot borrow `queue` as mutable because it is also borrowed as immutable
<anon>:8             queue.pop();
                     ^~~~~
<anon>:5:21: 5:26 note: previous borrow of `queue` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `queue` until the borrow ends
<anon>:5         let entry = queue.peek().unwrap();
                             ^~~~~
<anon>:10:6: 10:6 note: previous borrow ends here
<anon>:4     while !queue.is_empty() {
...
<anon>:10     }
              ^

问题是这个借用了queue:

let entry = queue.peek().unwrap();

peek() returns 一个 Option<&T>,即一个选项引用了 T 类型的值。只要 entry 还活着,借用就有效,直到函数结束。它指向存储在堆内的东西,所以它不可变地借用了堆。换句话说,只要 entry 还活着(直到函数结束),堆就会被不可变地借用。

queue.pop() 以可变方式借用堆,因此,当您到达那里时,堆已以不可变方式借用,并且您尝试同时以可变方式借用它。

借用检查器规则规定,您不能同时借用可变和不可变的东西,所以您遇到了问题。

要解决这个问题,请想办法避免同时借入两次。例如,您可以这样做:

fn check_the_queue(mut queue: BinaryHeap<i32>) {
    while !queue.is_empty() {
        if *queue.peek().unwrap() <= 0 {
            queue.pop();
        } 
    }
}

也就是去掉变量entry即可。这是有效的,因为当你达到 queue.pop() 时,没有其他活动的借用,并且借用检查器很高兴:)

生命周期和借用规则一开始可能很难理解,但陡峭的学习曲线会随着时间的推移得到回报。