如何在Rust中交换向量、切片或数组中的项目?

45

我的代码看起来像这样:

fn swap<T>(mut collection: Vec<T>, a: usize, b: usize) {
    let temp = collection[a];
    collection[a] = collection[b];
    collection[b] = temp;
}

Rust相信我无法“移动解除引用”或“移动索引内容”,不管那是什么意思。我该如何说服Rust这是可能的?

2个回答

79

有一个&mut [T]定义的swap方法。由于Vec<T>可以被可变地解引用&mut [T],因此可以直接调用此方法:

fn main() {
    let mut numbers = vec![1, 2, 3];
    println!("before = {:?}", numbers);
    numbers.swap(0, 2);
    println!("after = {:?}", numbers);
}

为了自己实现这个功能,你需要编写一些不安全的代码。Vec::swap 的实现如下所示:
fn swap(&mut self, a: usize, b: usize) {
    unsafe {
        // Can't take two mutable loans from one vector, so instead just cast
        // them to their raw pointers to do the swap
        let pa: *mut T = &mut self[a];
        let pb: *mut T = &mut self[b];
        ptr::swap(pa, pb);
    }
}

这段代码从向量中获取了两个裸指针,并使用 ptr::swap 安全地交换它们。

当你需要交换两个不同的变量时,也可以使用 mem::swap(&mut T, &mut T)。但是在这里无法使用,因为 Rust 不允许从同一个向量中取出两个可变借用。


20

正如 @gsingh2011 所提到的,被接受的答案已经不再是一个好方法。使用当前版本的 Rust,这段代码可以正常工作:

fn main() {
    let mut numbers = vec![1, 2, 3];
    println!("before = {:?}", numbers);
    numbers.swap(0, 2);
    println!("after = {:?}", numbers);
}

在这里尝试一下


4
我已经更新了另一个答案,因此这个答案现在已经过时。 - Shepmaster

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接