Rust’s Copy vs. Clone: Was ist der Unterschied?
Grace Collins
Solutions Engineer · Leapcell

Gute Brüder: Copy und Clone in Rust
In Rust steuern die Traits Copy und Clone das Kopierverhalten von Typen. Sie ermöglichen es dir, zu definieren, wie Werte eines Typs kopiert werden und unter welchen Umständen das Kopieren erlaubt ist. Dieser Artikel wird den Zweck und die Verwendung dieser beiden Traits im Detail vorstellen, zusammen mit Codebeispielen, die ihre Verwendung demonstrieren.
Der Copy Trait
Der Copy Trait signalisiert, dass ein Typ bitweise kopiert werden kann. Wenn ein Typ den Copy Trait implementiert, werden seine Werte automatisch dupliziert, wenn sie zugewiesen, als Argumente übergeben oder zurückgegeben werden.
Was ist der Copy Trait?
Der Copy Trait ist ein Marker-Trait, was bedeutet, dass er keine Methoden definiert. Er markiert einen Typ lediglich als geeignet für bitweises Kopieren.
#[derive(Copy)] struct Point { x: i32, y: i32, }
Wie man den Copy Trait implementiert?
Um den Copy Trait zu implementieren, musst du das Attribut #[derive(Copy)] zur Typdefinition hinzufügen. Zusätzlich muss der Typ auch den Clone Trait implementieren, da alle Typen, die Copy implementieren, auch Clone implementieren müssen.
#[derive(Copy, Clone)] struct Point { x: i32, y: i32, }
Wenn du versuchst, Copy zu implementieren, ohne auch Clone zu implementieren, wirft der Compiler einen Fehler:
#[derive(Copy)] struct Point { x: i32, y: i32, } // error[E0277]: the trait bound `Point: std::clone::Clone` is not satisfied
Die Fehlermeldung zeigt an, dass der Typ Point den Clone Trait nicht implementiert und daher Copy nicht implementieren kann.
Diese Anforderung existiert, weil alle Copy-Typen auch Clone implementieren müssen. Wenn du explizit die clone-Methode aufrufst, geht Rust davon aus, dass du beabsichtigst, eine Kopie zu erstellen und möchte sicherstellen, dass das Kopierverhalten wohldefiniert ist. Wenn du also Copy implementieren möchtest, musst du auch Clone implementieren.
Welche Typen können Copy implementieren?
Nicht alle Typen können Copy implementieren. Nur Typen, die die folgenden Kriterien erfüllen, sind geeignet:
- Der Typ selbst ist ein Plain Old Data (POD) Typ, was bedeutet, dass er keine Pointer oder Referenzen enthält.
- Alle Felder des Typs müssen ebenfalls
Copyimplementieren.
Zum Beispiel kann der folgende Typ nicht Copy implementieren, weil er ein Referenzfeld enthält:
struct Foo<'a> { x: &'a i32, } // error[E0204]: the trait `Copy` may not be implemented for this type impl Copy for Foo<'_> {}
Warum brauchen wir den Copy Trait?
Der Copy Trait ermöglicht die Kontrolle über das Kopierverhalten eines Typs. Wenn ein Typ Copy implementiert, werden seine Werte automatisch bei Zuweisung, Funktionsparameterübergabe und Rückgabe dupliziert. Dies eliminiert die Notwendigkeit, explizit clone() aufzurufen, um Werte zu kopieren.
Darüber hinaus ist der Performance-Overhead minimal, da Copy-Typen immer bitweise kopiert werden. Dies ist besonders nützlich, um die Performance in Rust-Programmen zu optimieren.
Der Clone Trait
Im Gegensatz zu Copy erlaubt der Clone Trait das explizite Kopieren des Werts eines Typs. Wenn ein Typ Clone implementiert, kannst du seine clone()-Methode aufrufen, um eine neue Instanz zu erstellen.
Was ist der Clone Trait?
Im Gegensatz zu Copy ist Clone ein regulärer Trait, der eine Methode enthält: clone(). Diese Methode ist dafür verantwortlich, eine neue Kopie des Werts zu erstellen.
#[derive(Clone)] struct Point { x: i32, y: i32, }
Wie man den Clone Trait implementiert?
Um den Clone Trait zu implementieren, kannst du entweder das Attribut #[derive(Clone)] hinzufügen oder die clone()-Methode manuell implementieren.
#[derive(Clone)] struct Point { x: i32, y: i32, } // Manuelles Implementieren der `clone()`-Methode impl Clone for Point { fn clone(&self) -> Self { Self { x: self.x, y: self.y } } }
Welche Typen können Clone implementieren?
Fast alle Typen können Clone implementieren. Solange du definieren kannst, wie eine neue Kopie eines Werts erstellt werden soll, kannst du Clone implementieren.
Warum brauchen wir den Clone Trait?
Der Clone Trait ermöglicht die explizite Duplizierung von Werten. Dies ist besonders nützlich für Typen, die nicht bitweise kopiert werden können, wie z.B. solche, die Pointer oder Referenzen enthalten.
Zusätzlich erlaubt Clone die Anpassung des Kopiervorgangs. Du kannst jede notwendige Logik innerhalb der clone()-Methode hinzufügen, um bestimmte Aktionen während des Kopierens durchzuführen.
Unterschiede und Beziehung zwischen Copy und Clone
Sowohl Copy als auch Clone steuern, wie Typen kopiert werden, aber sie haben wichtige Unterschiede:
Copyist ein Marker-Trait, der anzeigt, dass ein Typ bitweises Kopieren unterstützt. Wenn ein TypCopyimplementiert, werden seine Werte automatisch bei Zuweisung, Übergabe als Funktionsargumente und Rückgabe dupliziert.Cloneist ein regulärer Trait, der eine Methode enthält:clone(). Wenn ein TypCloneimplementiert, kannst du explizitclone()aufrufen, um eine neue Kopie zu erstellen.
Zusätzlich müssen alle Copy-Typen auch Clone implementieren. Dies stellt sicher, dass Rust davon ausgeht, dass du weißt, was du tust, wenn du explizit clone() aufrufst, und erlaubt bitweises Kopieren.
Beispielanalyse
Unten ist ein Beispiel, das die Verwendung von Copy und Clone demonstriert:
#[derive(Copy, Clone)] struct Point { x: i32, y: i32, } fn main() { let p1 = Point { x: 1, y: 2 }; let p2 = p1; // Automatisch kopiert let p3 = p1.clone(); // Explizit kopiert }
In diesem Beispiel definieren wir einen Point-Typ und implementieren sowohl die Copy- als auch die Clone-Traits. In der main-Funktion erstellen wir einen Point-Wert und weisen ihn einer anderen Variablen zu. Da Point Copy implementiert, dupliziert die Zuweisungsoperation den Wert automatisch. Zusätzlich rufen wir explizit clone() auf, um eine weitere Kopie des Werts zu erstellen.
Wir sind Leapcell, Ihre erste Wahl für das Hosting von Rust-Projekten.
Leapcell ist die Serverless-Plattform der nächsten Generation für Webhosting, asynchrone Aufgaben und Redis:
Multi-Language-Support
- Entwickeln Sie mit Node.js, Python, Go oder Rust.
Stellen Sie unbegrenzt Projekte kostenlos bereit
- Zahlen Sie nur für die Nutzung - keine Anfragen, keine Gebühren.
Unschlagbare Kosteneffizienz
- Pay-as-you-go ohne Leerlaufgebühren.
- Beispiel: 25 $ unterstützen 6,94 Millionen Anfragen bei einer durchschnittlichen Antwortzeit von 60 ms.
Optimierte Entwicklererfahrung
- Intuitive Benutzeroberfläche für mühelose Einrichtung.
- Vollautomatisierte CI/CD-Pipelines und GitOps-Integration.
- Echtzeitmetriken und -protokollierung für verwertbare Erkenntnisse.
Mühelose Skalierbarkeit und hohe Leistung
- Auto-Skalierung zur einfachen Bewältigung hoher Parallelität.
- Kein operativer Overhead - konzentrieren Sie sich einfach auf das Bauen.
Erfahren Sie mehr in der Dokumentation!
Folgen Sie uns auf X: @LeapcellHQ



