In Rust, cloning creates a deep copy of data, especially for types that are stored on the heap like String and Vec. You use the clone() method to manually duplicate such values when ownership would otherwise be moved.
When a value in Rust is not a Copy type, assigning it or passing it to a function usually moves ownership. If you want to make a complete, independent copy of that value instead, you use cloning.
In this post, I will explain what cloning does, when to use it, and how it compares to shallow copying. If you have already read Copy vs. Move Semantics, this will feel like a natural next step.
What Is Cloning?
Cloning means creating a deep copy of data. This is different from simply copying a reference or assigning a value. In Rust, types like String and Vec store their data on the heap. Cloning them duplicates that data.
Example
let a = String::from("hello");
let b = a.clone();
println!("a: {}, b: {}", a, b);
Without clone(), the value would move from a to b, and a would become invalid. But cloning makes a full copy, so both variables are usable.
Why Clone Is Not Automatic
Rust makes you call clone() explicitly because:
- Heap cloning can be expensive
- You should only do it when necessary
- It makes ownership clear in your code
This design helps avoid performance problems by making you think about memory usage.
Types That Implement Clone
Many types in Rust implement the Clone trait:
- String
- Vec<T>
- Box<T>
- HashMap
- Custom structs (if all fields are Clone)
You can also make your own types Clone:
#[derive(Clone)]
struct User {
name: String,
age: u8,
}
Now you can write:
let u1 = User { name: String::from("Alice"), age: 30 };
let u2 = u1.clone();
This copies all fields, including the heap-allocated String inside.
Cloning vs Copying
Feature | Copy | Clone |
---|---|---|
Type | Stack-only types | Heap or complex types |
Performance | Fast | Slower (heap allocation) |
Usage | Automatic on assignment | Manual: you call clone() |
Trait | Copy trait | Clone trait |
Most primitive types like i32 and bool are Copy, so you do not need to clone them. Strings, vectors, and user-defined types usually need clone().
When to Clone
Use clone() when you need to keep using a value after moving it, or you want two independent copies of a complex type, or you want to return the same data from multiple branches or scopes.
Avoid overusing clone just to “make things work.” Borrowing with references is often a better and cheaper choice.
Common Mistake: Cloning in a Loop
let names = vec![String::from("Alice"), String::from("Bob")];
for name in names {
println!("{}", name);
}
// println!("{:?}", names); // moved
Fix it with clone:
let names = vec![String::from("Alice"), String::from("Bob")];
for name in names.clone() {
println!("{}", name);
}
println!("{:?}", names); // works now
But be careful as cloning a large vector can be expensive.
Summary
Cloning in Rust creates a deep copy of a value and its heap data. It is useful when you want to keep using a value after ownership would normally move. Rust requires you to use clone() explicitly to stay efficient and clear about memory usage.