[英]How to swap the elements of an array, slice, or Vec?
我想使用庫函數交換切片data
元素,但由於多次借用而不起作用:
use std::mem;
fn example() {
let mut data = [1, 2, 3];
let i = 0;
let j = 1;
mem::swap(&mut data[i], &mut data[j]);
}
error[E0499]: cannot borrow `data[_]` as mutable more than once at a time
--> src/lib.rs:8:29
|
8 | mem::swap(&mut data[i], &mut data[j]);
| --------- ------------ ^^^^^^^^^^^^ second mutable borrow occurs here
| | |
| | first mutable borrow occurs here
| first borrow later used by call
|
可以手動完成,但我不認為每次都使用此代碼很好:
let temp = data[i];
data[i] = data[j];
data[j] = temp;
有沒有其他解決方案來交換切片中的元素?
切片上有一個swap
方法: data.swap(i, j)
。
原始代碼不起作用,因為該語言要求&mut
不使用別名,也就是說,如果可以通過&mut
訪問一段數據,那么一定沒有其他方法可以使用該數據。 通常,對於連續索引data[i]
、 data[j]
,編譯器無法保證i
和j
不同。 如果它們相同,那么索引指的是相同的內存,因此&mut data[i]
和&mut data[j]
將是指向相同數據的兩個指針:非法!
.swap
在內部使用了一些unsafe
代碼,確保正確處理i == j
情況,避免混淆&mut
指針。 這就是說,它並沒有使用unsafe
,它只是確保這種“原始”的操作具有高性能(我絕對可以想像未來的語言/庫的改進,通過使這里減少需要不安全的要求不變更容易表達),例如以下是一個安全的實現:
use std::cmp::Ordering;
use std::mem;
fn swap<T>(x: &mut [T], i: usize, j: usize) {
let (lo, hi) = match i.cmp(&j) {
// no swapping necessary
Ordering::Equal => return,
// get the smallest and largest of the two indices
Ordering::Less => (i, j),
Ordering::Greater => (j, i),
};
let (init, tail) = x.split_at_mut(hi);
mem::swap(&mut init[lo], &mut tail[0]);
}
這里的關鍵是split_at_mut
它將切片分成兩個不相交的部分(這是在內部使用unsafe
完成的,但 Rust 的標准庫建立在unsafe
之上:語言提供“原始”特性,而庫在它們之上構建其余部分)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.