Dieses Problem scheint zu implizieren, dass es sich nur um ein Implementierungsdetail handelt ( memcpyvs ???), aber ich kann keine explizite Beschreibung der Unterschiede finden.
Dieses Problem scheint zu implizieren, dass es sich nur um ein Implementierungsdetail handelt ( memcpyvs ???), aber ich kann keine explizite Beschreibung der Unterschiede finden.
Antworten:
Cloneist für beliebige Duplikate ausgelegt: Eine CloneImplementierung für einen Typ Tkann beliebig komplizierte Operationen ausführen, die zum Erstellen eines neuen erforderlich sind T. Es ist ein normales Merkmal (außer im Vorspiel) und erfordert daher die Verwendung wie ein normales Merkmal mit Methodenaufrufen usw.
Das CopyMerkmal stellt Werte dar, die sicher dupliziert werden können über memcpy: Dinge wie Neuzuweisungen und das Übergeben eines Argument-By-Value an eine Funktion sind immer memcpys, und daher Copyversteht der Compiler für Typen, dass er diese nicht als Verschiebung betrachten muss .
Clonees sich um eine Tiefenkopie und Copyeine Schattenkopie handelt?
Cloneeröffnet die Möglichkeit, dass der Typ entweder eine tiefe oder eine flache Kopie erstellt: "willkürlich kompliziert".
Der Hauptunterschied besteht darin, dass das Klonen explizit ist. Implizite Notation bedeutet Verschieben für einen Nicht- CopyTyp.
// u8 implements Copy
let x: u8 = 123;
let y = x;
// x can still be used
println!("x={}, y={}", x, y);
// Vec<u8> implements Clone, but not Copy
let v: Vec<u8> = vec![1, 2, 3];
let w = v.clone();
//let w = v // This would *move* the value, rendering v unusable.
Übrigens muss auch jeder CopyTyp sein Clone. Sie müssen jedoch nicht dasselbe tun! .clone()Kann für Ihre eigenen Typen eine beliebige Methode Ihrer Wahl sein, während implizites Kopieren immer eine memcpyund nicht die clone(&self)Implementierung auslöst .
yeinen Umzug erhalten x, keine Kopie davon, wie in Ihrem letzten auskommentierten Beispiel w = v. Wie würden Sie das spezifizieren?
Copyes für "billige" Typen implementiert werden soll, wie u8im Beispiel. Wenn Sie einen ziemlich schweren Typ schreiben, für den Sie glauben, dass ein Zug effizienter ist als eine Kopie, lassen Sie ihn nicht implizieren Copy. Beachten Sie, dass Sie im U8-Fall mit einem Umzug möglicherweise nicht effizienter sein können, da unter der Haube wahrscheinlich zumindest eine Zeigerkopie erforderlich ist - die bereits so teuer ist wie eine U8-Kopie. Warum also die Mühe machen?
CopyMerkmals einen Einfluss auf den impliziten Lebensbereich von Variablen hat? Wenn ja, finde ich das bemerkenswert.
Wie bereits von anderen Antworten abgedeckt:
Copy ist implizit, kostengünstig und kann nicht erneut implementiert werden (memcpy).Clone ist explizit, kann teuer sein und kann willkürlich neu implementiert werden.Was manchmal in der Diskussion von Copyvs fehlt, Cloneist, dass es auch beeinflusst, wie der Compiler Moves vs automatische Kopien verwendet. Zum Beispiel:
#[derive(Debug, Clone, Copy)]
pub struct PointCloneAndCopy {
pub x: f64,
}
#[derive(Debug, Clone)]
pub struct PointCloneOnly {
pub x: f64,
}
fn test_copy_and_clone() {
let p1 = PointCloneAndCopy { x: 0. };
let p2 = p1; // because type has `Copy`, it gets copied automatically.
println!("{:?} {:?}", p1, p2);
}
fn test_clone_only() {
let p1 = PointCloneOnly { x: 0. };
let p2 = p1; // because type has no `Copy`, this is a move instead.
println!("{:?} {:?}", p1, p2);
}
Das erste Beispiel ( PointCloneAndCopy) funktioniert hier aufgrund der impliziten Kopie einwandfrei, aber das zweite Beispiel ( PointCloneOnly) würde bei einer Verwendung nach dem Verschieben einen Fehler verursachen:
error[E0382]: borrow of moved value: `p1`
--> src/lib.rs:20:27
|
18 | let p1 = PointCloneOnly { x: 0. };
| -- move occurs because `p1` has type `PointCloneOnly`, which does not implement the `Copy` trait
19 | let p2 = p1;
| -- value moved here
20 | println!("{:?} {:?}", p1, p2);
| ^^ value borrowed here after move
Um die implizite Verschiebung zu vermeiden, könnten wir explizit aufrufen let p2 = p1.clone();.
Dies kann die Frage aufwerfen, wie eine Bewegung eines Typs erzwungen werden kann, der das Merkmal Kopieren implementiert. . Kurze Antwort: Sie können / machen keinen Sinn.