clone method works exactly the same as a copy method, the difference being that a clone will return an object with the copied contents. So this saves some trouble of creating the second object before copy.
Differs from Copy in that Copy is implicit and extremely inexpensive, while Clone is always explicit and may or may not be expensive. In order to enforce these characteristics, Rust does not allow you to reimplement Copy , but you may reimplement Clone and run arbitrary code.
The Java Object clone() method creates a shallow copy of the object. Here, the shallow copy means it creates a new object and copies all the fields and methods associated with the object. The syntax of the clone() method is: object.clone()
Disk cloning is the process of creating a 1-to-1 copy of a hard disk drive (HDD) or solid-state drive (SSD), not just its files. Disk cloning may be used for upgrading a disk or replacing an aging disk with a fresh one. In this case, the clone can replace the original disk in its host computer.
Clone
is designed for arbitrary duplications: a Clone
implementation for a type T
can do arbitrarily complicated operations required to create a new T
. It is a normal trait (other than being in the prelude), and so requires being used like a normal trait, with method calls, etc.
The Copy
trait represents values that can be safely duplicated via memcpy
: things like reassignments and passing an argument by-value to a function are always memcpy
s, and so for Copy
types, the compiler understands that it doesn't need to consider those a move.
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.
As already covered by other answers:
Copy
is implicit, inexpensive, and cannot be re-implemented (memcpy).Clone
is 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);
}
(Rust Playground)
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With