簡體   English   中英

如何交換數組、切片或 Vec 的元素?

[英]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] ,編譯器無法保證ij不同。 如果它們相同,那么索引指的是相同的內存,因此&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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM