In this lesson, you will learn how to distinguish between the Copy and Clone traits and decide when it is appropriate to implement each for your custom types.
The Distinction
In Rust, every type has a default ownership behavior: move semantics. When you assign a variable to another, the value "moves," and the original variable becomes unusable. Copy and Clone are the two standard ways to change this behavior.
Copy(Bitwise Copy): This is for types that can be copied simply by duplicating their bits in memory. It is implicit and happens automatically during assignment. Because it is implicit,Copyis reserved for simple, lightweight data (like integers or small structs of integers).Clone(Explicit Copy): This is for types that require expensive or complex operations to duplicate, such as allocating memory on the heap (likeStringorVec). You must call the.clone()method manually to signal that an expensive operation is taking place.
When to Implement Which?
If a type implements Copy, it must also implement Clone. Think of Copy as a "superpower" version of Clone that lets the compiler handle the duplication for you.
#[derive(Debug, Clone, Copy)]
struct Point {
x: i32,
y: i32,
}
struct Logger {
buffer: String,
}
impl Clone for Logger {
fn clone(&self) -> Self {
// We implement Clone because we must allocate a new String
Logger { buffer: self.buffer.clone() }
}
}
// We CANNOT implement Copy for Logger because it owns heap memory.
The Rule of Thumb
- Can your type be copied by just copying its bytes? If yes, and it doesn't own resources like heap memory or file handles, you can implement
Copy. This makes your type ergonomic because it behaves like a primitive type. - Does your type own resources (e.g.,
String,Vec,Box)? If yes, you should implementCloneto allow the user to make an explicit copy. You cannot implementCopybecause copying these types would lead to double-free errors if two variables tried to clean up the same heap memory.
Key Takeaway: Implement Copy for cheap, bitwise-copyable types to gain implicit duplication, and reserve Clone for types that require explicit, potentially expensive resource management.