'What is the difference between Copy and Clone?
This issue seems to imply it's just an implementation detail (memcpy vs ???), but I can't find any explicit description of the differences.
Solution 1:[1]
The main difference is that cloning is explicit. Implicit notation means move for a non-Copy type.
// 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.
By the way, every Copy type is also required to be Clone. However, they are not required to do the same thing! For your own types, .clone() can be an arbitrary method of your choice, whereas implicit copying will always trigger a memcpy, not the clone(&self) implementation.
Solution 2:[2]
As already covered by other answers:
Copyis implicit, inexpensive, and cannot be re-implemented (memcpy).Cloneis explicit, may be expensive, and may be re-implement arbitrarily.
What is sometimes missing in the discussion of Copy vs Clone is that it also affects how the compiler uses moves vs automatic copies. For instance:
#[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);
}
The first example (PointCloneAndCopy) works fine here because of the implicit copy, but the second example (PointCloneOnly) would error with a use after move:
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
To avoid the implicit move, we could explicitly call let p2 = p1.clone();.
This may raise the question of how to force a move of a type which implements the Copy trait?.
Short answer: You can't / doesn't make sense.
Solution 3:[3]
As written here.
Copies happen implicitly, for example as part of an assignment
y = x. The behavior ofCopyis not overloadable; it is always a simple bit-wise copy.
Cloning is an explicit action,
x.clone(). The implementation ofClonecan provide any type-specific behavior necessary to duplicate values safely. For example, the implementation ofCloneforStringneeds to copy the pointed-to string buffer in the heap. A simple bitwise copy ofStringvalues would merely copy the pointer, leading to a double free down the line. For this reason,StringisClonebut notCopy.
Cloneis a supertrait ofCopy, so everything which isCopymust also implementClone. If a type isCopythen itsCloneimplementation only needs to return*self
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | JamesThomasMoon |
| Solution 3 | mdmundo |
