C.W.K.
Stream
Lesson 03 of 05 · published

Copy vs Clone

~11 min · ownership, copy, clone, derive

Level 0Rust Curious
0 XP0/80 lessons0/19 achievements
0/100 XP to next level100 XP to go0% complete

Last lesson left a question: why do some types move and others copy? The answer is two traits — Copy and Clone — and the line between them is one of Rust's cleanest design decisions.

Copy — implicit, free, stack-only

Types that live entirely on the stack and are trivially duplicable implement the Copy trait: all the integer and float types, bool, char, and tuples or arrays made only of Copy types. For these, let y = x; makes a bitwise copy and leaves x perfectly valid. No move, no fuss — duplicating eight bytes is cheaper than tracking ownership.

Clone — explicit, possibly expensive

Types that own heap data (String, vectors, hash maps) do not implement Copy, because duplicating them means a heap allocation and a byte-for-byte copy. That cost should never be invisible, so Rust makes you ask for it by name: let s2 = s1.clone();. Now both own independent buffers — and you chose that.

Rust never hides an expensive copy. If a heap allocation happens, you typed .clone(). This is why Rust code's performance is so readable — the costly operations are spelled out, not buried in an assignment operator.

Deriving them

For your own structs, you opt in with #[derive(Clone)] — and #[derive(Copy)] if every field is itself Copy. That one line tells the compiler to generate the duplication logic for you. You'll see #[derive(Clone, Debug)] on top of struct definitions constantly.

The habit to build

When you hit a move error, the lazy fix is to sprinkle .clone() until it compiles. Resist that. Each clone is a real allocation. Often the right answer is a reference — the next track — which borrows the data instead of duplicating it.

Code

Copy is implicit, Clone is explicit·rust
#[derive(Clone, Debug)] // generate Clone + Debug for this struct
struct Profile { name: String, age: u32 }

fn main() {
    // Copy type: assignment duplicates, original stays valid
    let a = 10;
    let b = a;            // copied
    println!("{a} {b}");  // both fine

    // Non-Copy: must clone explicitly to get two owners
    let p1 = Profile { name: String::from("Ferris"), age: 3 };
    let p2 = p1.clone();  // explicit deep copy (heap allocation)
    println!("{p1:?} {p2:?}");
}

External links

Exercise

Define a struct with one String field. Try #[derive(Copy)] on it and read the compiler error. Why won't Rust let a struct containing a String be Copy?
Hint
Copy means 'safe to duplicate with a bitwise stack copy.' A String owns a heap buffer, so a bitwise copy would create two owners of one allocation — exactly the double-free Rust forbids. Hence no Copy for heap-owning types.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue
💛 by Ttoriwarm

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.