Betrachten wir die Vorgeschichte der Frage:
In Rust erfordert das Konzept des Speicherverwaltungs- und Eigentumsmanagements eine klare Definition, wie Objekte bewegt und kopiert werden. Zu Beginn der Sprache war es wichtig, einfaches Kopieren von Bytes (ohne Allokationen und Logik) und tiefes Klonen (z.B. eine Kopie eines Strings, Vektors) zu unterscheiden. Zu diesem Zweck wurden zwei Traits eingeführt — Copy und Clone.
Das Problem ist, dass nicht alle Datentypen gleich günstig kopiert werden können. Für einige Strukturen ist Kopieren einfach eine Bitkopie (z.B. Ganzzahlen oder Tupel aus Copy-Typen), während für andere (z.B. String, Vec) zusätzliche Arbeiten zur Speicherallokation anfallen. Die Trennung von Copy und Clone ermöglicht es Rust, einen Kompilierungsfehler zu generieren, wenn versucht wird, eine ungültige Kopie zu erstellen.
Lösung:
Copy gekennzeichnet sind, werden automatisch beim Übertragen, Zuweisen und Übergeben an Funktionen kopiert. Objekte dieser Typen bleiben nach der Kopie gültig.Clone implementiert, das einen expliziten Aufruf der Methode .clone() erfordert, oft mit zusätzlichen Ressourcenallokationen.Beispielcode:
#[derive(Debug, Copy, Clone)] struct Point { x: i32, y: i32, } fn main() { let p1 = Point { x: 1, y: 2 }; let p2 = p1; // p1 wird nicht "ungültig" println!("{:?} {:?}", p1, p2); }
Wichtige Merkmale:
Copy - automatische bitweise Kopie, benötigt keinen manuellen Aufruf und beeinträchtigt das Eigentum nicht.Clone - explizite tiefe Kopie, geeignet für Strukturen mit Heap-Daten.Können Typen mit heap-allozierten Daten die Derivation von Copy haben?
Nein, Typen, die heap-Daten enthalten (z.B. String, Vec), können Copy nicht automatisch implementieren, da dies zu einer doppelten Freigabe des Speichers führen würde.
Wenn ein Typ Copy implementiert, kann man ihn dann auch manuell mit anderer Logik Clone implementieren?
Ja, Clone kann manuell implementiert werden und die Logik kann abweichen, es wird jedoch empfohlen, dass Copy und Clone konsistent sind: Copy ruft einfach Clone ohne Allokationen auf.
#[derive(Copy)] struct X; impl Clone for X { fn clone(&self) -> X { *self } }
Wenn eine Struktur nur Copy-Felder enthält, aber nicht mit #[derive(Copy)] gekennzeichnet ist, wird sie dann Copy?
Nein, ein Typ wird aufgrund seiner Zusammensetzung nicht automatisch Copy — eine explizite Derivation von Copy für Ihren Typ ist erforderlich.
Ein Typ mit heap-Daten wird fälschlicherweise als Copy markiert, was zu einer doppelten Speicherfreigabe beim Finalisieren führt.
Vorteile:
Nachteile:
Verwendung von Copy für leichte Strukturen (Koordinaten, Farben), Clone — für komplexe (Strings, Vektoren). Der Code ist sicher und vorhersehbar.
Vorteile:
Nachteile: