Здається, ця проблема передбачає, що це лише детальна інформація про впровадження ( memcpy
проти ???), але я не можу знайти явного опису відмінностей.
Здається, ця проблема передбачає, що це лише детальна інформація про впровадження ( memcpy
проти ???), але я не можу знайти явного опису відмінностей.
Відповіді:
Clone
призначений для довільних дублювань: Clone
реалізація для типу T
може робити довільно складні операції, необхідні для створення нового T
. Це нормальна ознака (крім того, що є прелюдією), і тому вимагає використання, як звичайна ознака, з викликами методів тощо.
Ця Copy
ознака представляє значення, які можна безпечно дублювати через memcpy
: такі речі, як перепризначення та передача функції-значення аргументу функції, завжди є memcpy
s, і тому для Copy
типів компілятор розуміє, що їм не потрібно вважати цей крок .
Clone
це копія, і Copy
як тіньова копія?
Clone
відкриває можливість того, що тип може зробити або глибоку, або дрібну копію: "довільно складно".
Основна відмінність полягає в тому, що клонування є явним. Неявне позначення означає переміщення для нетипового Copy
типу.
// 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.
До речі, Copy
вимагається також кожен тип Clone
. Однак вони не зобов’язані робити те саме! Для ваших власних типів .clone()
може бути довільним методом на ваш вибір, тоді як неявна копіювання завжди викликає a memcpy
, а не clone(&self)
реалізацію.
y
щоб отримати переміщений x
, а не його копію, як з вашого останнього закоментувавши прикладу w = v
. Як би ви це вказали?
Copy
призначений для впровадження для "дешевих" типів, як, наприклад, u8
у прикладі. Якщо ви пишете досить важкий тип, для якого ви вважаєте, що хід більш ефективний, ніж копія, зробіть це не імпортом Copy
. Зверніть увагу, що у випадку u8 ви не можете бути більш ефективними з переміщенням, оскільки під кришкою це, мабуть, спричинить принаймні копію вказівника - яка вже така ж дорога, як копія u8, то чому б це турбувати.
Copy
ознаки впливає на неявні сфери використання змінних? Якщо так, я вважаю, що це примітно.
Як уже висвітлено в інших відповідях:
Copy
неявна, недорога і не може бути повторно реалізована (memcpy).Clone
є явним, може бути дорогим і може бути повторно реалізовано довільно.Чого іноді не вистачає в обговоренні Copy
vs, Clone
це те, що це також впливає на те, як компілятор використовує переміщення проти автоматичних копій. Наприклад:
#[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);
}
Перший приклад ( PointCloneAndCopy
) працює тут чудово через неявну копію, але другий приклад ( PointCloneOnly
) помилиться при використанні після переміщення:
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
Щоб уникнути неявного ходу, ми могли б чітко зателефонувати let p2 = p1.clone();
.
Це може поставити питання про те, як змусити перемістити тип, який реалізує ознаку Copy? . Коротка відповідь: Ви не можете / не має сенсу.