简体   繁体   中英

How can I swap items in a vector, slice, or array in Rust?

My code looks like this:

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

Rust is pretty sure I'm not allowed to "move out of dereference" or "move out of indexed content", whatever that is. How do I convince Rust that this is possible?

There is a swap method defined for &mut [T] . Since a Vec<T> can be mutably dereferenced as a &mut [T] , this method can be called directly:

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

To implement this yourself, you have to write some unsafe code. Vec::swap is implemented like this:

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);
    }
}

It takes two raw pointers from the vector and uses ptr::swap to swap them safely.

There is also a mem::swap(&mut T, &mut T) when you need to swap two distinct variables. That cannot be used here because Rust won't allow taking two mutable borrows from the same vector.

As mentioned by @gsingh2011, the accepted answer is no longer good approach. With current Rust this code works fine:

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

try it here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM