2016-07-06 29 views
6

Ho un enum in Rust che ha un valore che prende uno String. Questo può essere dimostrato con questo semplice esempio:Come implementare Clone/Copia per un enum che contiene una stringa?

#[derive(Clone, Copy)] 
enum Simple { 
    Error(String), 
    Okay, 
    Foo([u32; 5]), 
} 

fn main() { 
    let x = Simple::Error(String::from("blah")); 
    let y = x.clone(); 
} 

Il valore di enumerazione Foo sopra rappresenta circa altre 10 enums che uso che prendono tipi copiabili o array di loro. Il compilatore non sembra lamentarsi di loro, solo il Error(String) che causa questo:

error: the trait `Copy` may not be implemented for this type; variant `Error` does not implement `Copy` [E0205] 
#[derive(Clone, Copy)] 
       ^~~~ 

note: in this expansion of #[derive_Copy] (defined in src\main.rs) 
help: run `rustc --explain E0205` to see a detailed explanation 

Per qualche ragione String non è copiabile. Non capisco questo Come implementare Clone per un enum solo per il tipo che ha un problema mentre si utilizza l'impl di default per il resto?

risposta

16

Copy indica tipi per cui la creazione di una copia bit a bit crea un'istanza valida senza invalidare l'istanza originale. Questo non è vero per String, perché String contiene un puntatore ai dati di stringa sull'heap e presuppone che abbia una proprietà univoca di tali dati, e quindi quando si rilascia uno String, rilascia i dati sull'heap e, se lo si è fatto una copia bit a bit di String, quindi entrambe le istanze proverebbero a deallocare lo stesso blocco di memoria, ovvero comportamento non definito. Poiché String non implementa Copy, il tuo enum non può implementare Copy o, perché il compilatore impone che i tipi Copy siano composti solo da membri dati Copy.

Clone fornisce semplicemente un metodo standard clone e spetta a ciascun implementatore decidere come implementarlo. String implementa Clone, quindi può mettere #[derive(Clone)] sul enum.

+0

Aggiungo Non vedo perché String non può implementare un tratto Copia in linea di principio o pratica - Gli oggetti QString in QT possono essere copiati e condividono e gestiscono un buffer interno. Se una copia fa qualcosa di mutabile, il buffer viene prima clonato in modo che altre copie mantengano ancora un riferimento al buffer originale. In QT è ancora meglio passare per riferimento per evitare il conteggio dei ref atomici ma la copia è comunque efficiente. – locka

+0

@locka perché * "Copia" indica i tipi per i quali creare una copia bit a bit crea un'istanza valida *. Copiare i bit di una stringa di questo tipo non poteva incrementare un contatore atomico, perché non avrebbe più dovuto copiarlo. Devi scegliere quali garanzie hai bisogno. Puoi [condividere la proprietà] (http://doc.rust-lang.org/std/rc/struct.Rc.html), [condividere la proprietà sui thread] (http://doc.rust-lang.org/std /sync/struct.Arc.html), implementa [clone on write] (http://doc.rust-lang.org/std/borrow/enum.Cow.html), ecc. Non sarebbe un bene per un sistema lingua per prendere quella decisione (e caricare il tuo codice) per te. – Shepmaster

Problemi correlati