Consideriamo la storia della questione:
In Rust, il concetto di gestione della memoria e di proprietà richiede una chiara definizione di come gli oggetti vengono spostati e copiati. All'alba del linguaggio era importante distinguere tra la semplice copia di byte (senza allocazioni e logica) e la clonazione profonda (ad esempio, una copia di una stringa, un vettore). A tal fine, sono stati introdotti due trait — Copy e Clone.
Il problema è che non tutti i tipi di dati possono essere copiati a basso costo in modo equivalente. Per alcune strutture, la copia è semplicemente una copia di bit (ad esempio, numeri interi o tuple di tipi Copy), mentre per altre (ad esempio, String, Vec) è necessaria un'opera aggiuntiva per allocare memoria. La distinzione tra Copy e Clone consente a Rust di generare un errore di compilazione se si tenta di eseguire una copia non valida.
Soluzione:
Copy vengono copiati automaticamente durante la trasmissione, l'assegnazione e il passaggio a funzioni. Gli oggetti di tali tipi rimangono validi dopo la copia.Clone, che richiede la chiamata esplicita del metodo .clone(), spesso con un'ulteriore allocazione di risorse.Esempio di codice:
#[derive(Debug, Copy, Clone)] struct Point { x: i32, y: i32, } fn main() { let p1 = Point { x: 1, y: 2 }; let p2 = p1; // p1 non diventa "non valido" println!("{:?} {:?}", p1, p2); }
Caratteristiche chiave:
Copy - copia bit per bit automatica, non richiede chiamata manuale e non influisce sulla proprietà.Clone - copia profonda esplicita, adatta per strutture con dati heap.Possono i tipi con dati allocati nell'heap avere derivazione Copy?
No, i tipi contenenti dati heap (ad esempio, String, Vec) non possono implementare automaticamente Copy, poiché ciò porterebbe a una duplice liberazione della memoria.
Se un tipo implementa Copy, può anche implementare Clone manualmente con una logica diversa?
Sì, Clone può essere implementato manualmente e la logica può differire, tuttavia si raccomanda che Copy e Clone siano coerenti: Copy chiama semplicemente Clone senza allocazioni.
#[derive(Copy)] struct X; impl Clone for X { fn clone(&self) -> X { *self } }
Se una struttura contiene solo campi Copy, ma non è contrassegnata con #[derive(Copy)], diventerà Copy?
No, un tipo non diventa Copy automaticamente in base alla composizione — è necessaria una derivazione esplicita di Copy per il tuo tipo.
Un tipo con dati heap contrassegnato erroneamente come Copy causa una duplice liberazione della memoria al momento della finalizzazione.
Vantaggi:
Svantaggi:
Utilizzare Copy per strutture leggere (coordinate, colori), Clone — per quelle complesse (stringhe, vettori). Il codice è sicuro e prevedibile.
Vantaggi:
Svantaggi: