Dieses Problem scheint zu implizieren, dass es sich nur um ein Implementierungsdetail handelt ( memcpy
vs ???), aber ich kann keine explizite Beschreibung der Unterschiede finden.
Dieses Problem scheint zu implizieren, dass es sich nur um ein Implementierungsdetail handelt ( memcpy
vs ???), aber ich kann keine explizite Beschreibung der Unterschiede finden.
Antworten:
Clone
ist für beliebige Duplikate ausgelegt: Eine Clone
Implementierung für einen Typ T
kann 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 Copy
Merkmal 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 memcpy
s, und daher Copy
versteht der Compiler für Typen, dass er diese nicht als Verschiebung betrachten muss .
Clone
es sich um eine Tiefenkopie und Copy
eine Schattenkopie handelt?
Clone
erö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- Copy
Typ.
// 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 Copy
Typ 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 memcpy
und nicht die clone(&self)
Implementierung auslöst .
y
einen Umzug erhalten x
, keine Kopie davon, wie in Ihrem letzten auskommentierten Beispiel w = v
. Wie würden Sie das spezifizieren?
Copy
es für "billige" Typen implementiert werden soll, wie u8
im 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?
Copy
Merkmals 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 Copy
vs fehlt, Clone
ist, 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.