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
Copy
implementieren.
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:
Copy
ist ein Marker-Trait, der anzeigt, dass ein Typ bitweises Kopieren unterstützt. Wenn ein TypCopy
implementiert, werden seine Werte automatisch bei Zuweisung, Übergabe als Funktionsargumente und Rückgabe dupliziert.Clone
ist ein regulärer Trait, der eine Methode enthält:clone()
. Wenn ein TypClone
implementiert, 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