为什么我得到 "cannot borrow `arr[_]` as mutable more than once at a time"?
Why I got "cannot borrow `arr[_]` as mutable more than once at a time"?
我有一个使用 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 借用检查器非常复杂,但也有局限性。在这里,即使对于人类来说很明显没有发生可变别名,这个事实对借用检查器来说是完全隐藏的。它看到 &mut arr[j]
和 &mut arr[j + 1]
并得出结论:“你试图从 arr
两次可变地借用”。
错误消息确实指出了解决方案:
split_at_mut()
正是针对这种情况提供的。在幕后,它使用 unsafe
以一种仍然合理且不会导致 UB 的方式弯曲上述规则。它需要一个索引和 returns 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]);
因此,在您的情况下,您可以这样做,而不是使用 &mut arr[j]
来获取对数字的可变引用:
let (start, end) = arr.split_at_mut(1);
swap(&mut start[0], &mut end[0]);
P.S。切片还有 .swap(i, j)
:-D
我有一个使用 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 借用检查器非常复杂,但也有局限性。在这里,即使对于人类来说很明显没有发生可变别名,这个事实对借用检查器来说是完全隐藏的。它看到 &mut arr[j]
和 &mut arr[j + 1]
并得出结论:“你试图从 arr
两次可变地借用”。
错误消息确实指出了解决方案:
split_at_mut()
正是针对这种情况提供的。在幕后,它使用 unsafe
以一种仍然合理且不会导致 UB 的方式弯曲上述规则。它需要一个索引和 returns 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]);
因此,在您的情况下,您可以这样做,而不是使用 &mut arr[j]
来获取对数字的可变引用:
let (start, end) = arr.split_at_mut(1);
swap(&mut start[0], &mut end[0]);
P.S。切片还有 .swap(i, j)
:-D