Эта проблема, кажется, подразумевает, что это просто деталь реализации ( 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? , Краткий ответ: вы не можете / не имеет смысла.