【问题标题】:Why I got "cannot borrow `arr[_]` as mutable more than once at a time"?为什么我得到“不能一次多次借用`arr [_]`作为可变的”?
【发布时间】:2021-10-24 03:10:56
【问题描述】:

我有一个使用 Rust 创建冒泡排序的编程任务。我在 Rust 方面并没有太多经验,所以这对我来说有点困难:

fn main() {
    println!("Sort numbers ascending");
    let num:[i32; 10] = [4, 65, 2, -31, 0, 99, 2, 83, 782, 1];
    println!("Before: {:?}", num);
    bubble_sort( num);
    println!("After: {:?}\n", num);
}

fn swap( a: &mut i32, b: &mut i32){
    let tmp: i32 = *b;
    *b=*a;
    *a=tmp;
}

fn bubble_sort(mut arr: [i32; 10]) {
    for i in 0..arr.len() {
        for j in 0..arr.len() - 1 - i {
            if arr[j] > arr[j + 1] {
                swap( &mut arr[j], &mut arr[j + 1]);
            }
        }
    }
}

错误:

Compiling playground v0.0.1 (/playground)
error[E0499]: cannot borrow `arr[_]` as mutable more than once at a time
  --> src/main.rs:19:24
   |
19 |                 swap( &mut arr[j], &mut arr[j + 1]);
   |                 ----  -----------  ^^^^^^^^^^^^^^^ second mutable borrow occurs here
   |                 |     |
   |                 |     first mutable borrow occurs here
   |                 first borrow later used by call
   |
   = help: consider using `.split_at_mut(position)` or similar method to obtain two mutable non-overlapping sub-slices

For more information about this error, try `rustc --explain E0499`.
error: could not compile `playground` due to previous error

【问题讨论】:

标签: rust swap mutable borrow


【解决方案1】:

Rust 借用检查器非常复杂,但也有局限性。在这里,即使对人类来说很明显没有可变的别名发生,这个事实对借用检查器是完全隐藏的。它看到&mut arr[j]&mut arr[j + 1] 并得出结论:“你试图从arr 可变地借用两次”。

错误信息确实指出了解决方法:

split_at_mut() 正是针对这种情况提供的。在引擎盖下,它使用unsafe 以一种仍然合理且不会导致 UB 的方式弯曲上述规则。它需要一个索引来拆分,并返回 2 个不重叠的可变切片。这是文档中的示例:

let mut v = [1, 0, 3, 0, 5, 6];
let (left, right) = v.split_at_mut(2);
assert_eq!(left, [1, 0]);
assert_eq!(right, [3, 0, 5, 6]);

因此,在您的情况下,您可以这样做:

let (start, end) = arr.split_at_mut(1);
swap(&mut start[0], &mut end[0]);

附:还有.swap(i, j) 用于切片:-D

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-13
    • 2023-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-25
    相关资源
    最近更新 更多