2014-08-27 10 views
5

Mój kod wygląda następująco:Jak mogę zamienić elementy w wektorze, wycinku lub macierzy w Rust?

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

Rust jest całkiem pewny, że nie wolno mi „wyjść z dereference” lub „wyprowadzić z indeksowanej zawartości”, cokolwiek to znaczy. Jak przekonać Rusta, że ​​to możliwe?

Odpowiedz

15

Istnieje swap method defined for &mut [T]. Ponieważ Vec<T> może być mutably dereferenced jako &mut [T], metoda ta może być wywołana bezpośrednio:

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

Aby to realizować siebie, trzeba napisać jakiś niebezpieczny kod. Vec::swap is implemented tak:

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

trwa dwa surowe wskaźniki z wektora i wykorzystuje ptr::swap aby zamienić je bezpiecznie.

Istnieje również mem::swap(&mut T, &mut T), kiedy trzeba zamienić dwie różne zmienne. Tego nie można tu użyć, ponieważ Rust nie zezwala na wzięcie dwóch zmiennych pożyczek z tego samego wektora.

2

Jak wspomniano w @ gsingh2011, przyjęta odpowiedź nie jest już dobrym podejściem. Przy obecnym Rust ten kod działa poprawnie:

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

try it here

+2

zaktualizowałem drugą odpowiedź, tak teraz jest to zbędne. – Shepmaster

Powiązane problemy