Copy und Clone in Rust: Was ist der Unterschied und was wählen?

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Einleitung: Warum Copy und Clone nicht dasselbe sind?

\n\n

Jeder, der anfängt, Rust zu lernen, stößt früher oder später auf zwei rätselhafte Traits: Copy und Clone. Auf den ersten Blick tun sie dasselbe – sie ermöglichen es, ein Duplikat eines Wertes zu erhalten. Aber der Teufel steckt, wie immer, im Detail.

\n\n

Stellen Sie sich vor, Sie schreiben ein Programm und übergeben einen Wert an eine Funktion. In C++ wäre das eine Kopie (oder eine Verschiebung, wenn Sie Glück haben). In Python – einfach eine weitere Referenz auf das Objekt. Aber in Rust... Rust zwingt Sie, explizit zu entscheiden: "Ich möchte, dass dieser Wert kopiert wird" oder "Ich möchte ihn unter Berücksichtigung der Kosten klonen".

\n\n

Genau hier verläuft die Grenze zwischen Copy und Clone. Ersteres ist "einfaches Bit-für-Bit-Kopieren". Zweiteres ist "bewusstes, möglicherweise teures Duplizieren".

\n\n

Lassen Sie uns anhand von Beispielen verstehen, wann und was zu verwenden ist, damit Ihr Rust-Code nicht nur korrekt, sondern auch effizient ist.

\n\n

Das Wichtigste in Kürze: Copy vs Clone

\n\n

Was ist Clone?

\n\n

Clone ist ein Trait, der Ihnen die Methode .clone() zur Verfügung stellt. Wenn Sie sie aufrufen, sagen Sie dem Compiler explizit: "Ich weiß, dass dies teuer sein kann, aber ich brauche eine unabhängige Kopie."

\n\n

Eigenschaften von Clone:

\n
    \n
  • Kann für jeden Typ implementiert werden
  • \n
  • Erfordert einen expliziten Aufruf von .clone()
  • \n
  • Kann tiefe Kopien durchführen (z. B. für Vec oder String)
  • \n
  • Ändert nicht die Eigentumssemantik – nach dem Klonen haben Sie zwei unabhängige Werte
  • \n
\n\n

Was ist Copy?

\n\n

Copy ist ein "Marker"-Trait (ohne Methoden). Wenn ein Typ Copy implementiert, kann der Compiler seine Bits bei der Zuweisung oder Übergabe an eine Funktion einfach kopieren. Dies erfordert keinen Aufruf von .clone().

\n\n

Eigenschaften von Copy:

\n
    \n
  • Funktioniert nur für einfache Typen, die sicher bitweise kopiert werden können
  • \n
  • Erfordert keinen expliziten Aufruf – das Kopieren erfolgt automatisch
  • \n
  • Der Typ muss trotzdem Clone implementieren (es ist ein Supertrait)
  • \n
  • Der ursprüngliche Wert bleibt nach dem Kopieren gültig
  • \n
\n\n

Praktische Beispiele: Wie es im Code funktioniert

\n\n

Beispiel 1: Basistypen (Copy)

\n\n

Ganze Zahlen, Gleitkommazahlen, boolesche Werte – alle implementieren Copy:

\n\n
fn main() {\n    let x = 42;\n    let y = x; // x wird nach y kopiert, x ist weiterhin verfügbar\n    \n    println!("x = {}, y = {}", x, y); // Funktioniert!\n}
\n\n

Hier ist x ein i32, der Copy implementiert. Daher wird bei der Zuweisung y = x kopiert, und x bleibt gültig.

\n\n

Beispiel 2: String (nur Clone)

\n\n

String hingegen ist ein komplexer Typ, der Daten auf dem Heap speichert. Er implementiert Clone, aber nicht Copy:

\n\n
fn main() {\n    let s1 = String::from("Hallo, Rust!");\n    let s2 = s1; // s1 wird nach s2 verschoben\n    \n    // println!("{}", s1); // Fehler! s1 besitzt die Daten nicht mehr\n    \n    let s3 = s2.clone(); // So geht es – explizites Klonen\n    println!("s2 = {}, s3 = {}", s2, s3); // Funktioniert!\n}
\n\n

Warum kann String nicht Copy sein? Weil das bitweise Kopieren eines String zu zwei Zeigern auf denselben Heap-Speicher führen würde. Beim Drop beider Werte – doppelte Speicherfreigabe. Clone hingegen erstellt eine vollwertige, unabhängige Kopie.

\n\n

Beispiel 3: Eigener Typ mit Copy

\n\n

Sie können Ihren eigenen Typ Copy machen, wenn er nur aus Copy-Typen besteht:

\n\n
#[derive(Debug, Copy, Clone)]\nstruct Point {\n    x: f64,\n    y: f64,\n}\n\nfn main() {\n    let p1 = Point { x: 1.0, y: 2.0 };\n    let p2 = p1; // Wird kopiert, p1 bleibt erhalten\n    \n    println!                

Blogs

Buchempfehlungen