The Clone Trait
The Clone trait (std::clone::Clone) provides explicit, general-purpose value duplication via the .clone() method. Unlike Copy—which is restricted to implicit, cheap bitwise stack copies—Clone can perform arbitrary work, such as allocating a new heap buffer and deep-copying elements for String, Vec<T>, or HashMap<K, V>, or incrementing an atomic reference count for Arc<T>.
Definition of Clone
pub trait Clone: Sized {
fn clone(&self) -> Self;
fn clone_from(&mut self, source: &Self) {
*self = source.clone()
}
}
Because .clone(&self) takes an immutable shared reference &self and returns a brand-new owned Self, calling let b = a.clone(); never moves or invalidates a.
Deep Heap Duplication with `let s2 = s1.clone();`:
Stack Heap
+------------------+ +---+---+---+---+
| s1: String | ──> | r | u | s | t | (Original heap allocation)
+------------------+ +---+---+---+---+
| s2: String | ──> | r | u | s | t | (Newly allocated independent heap copy!)
+------------------+ +---+---+---+---+
fn main() {
let s1 = String::from("independent buffer");
let mut s2 = s1.clone(); // Allocates a second heap buffer with the same text
s2.push_str(" (modified)");
// `s1` is completely unaffected by mutating `s2`:
println!("s1 = '{s1}' (ptr = {:p})", s1.as_ptr());
println!("s2 = '{s2}' (ptr = {:p})", s2.as_ptr());
}
s1 = 'independent buffer' (ptr = 0x600000c14020)
s2 = 'independent buffer (modified)' (ptr = 0x600001718040)
Deriving Clone on Custom Structs and Enums (#[derive(Clone)])
You can automatically implement Clone on any struct or enum by adding #[derive(Clone)], provided every field or variant payload type also implements Clone:
#[derive(Debug, Clone, PartialEq)]
struct Document {
title: String,
tags: Vec<String>,
}
fn main() {
let template = Document {
title: String::from("Spec v1"),
tags: vec![String::from("draft")],
};
let mut copy = template.clone();
copy.title = String::from("Spec v2");
copy.tags.push(String::from("published"));
println!("template: {template:?}");
println!("copy: {copy:?}");
}
template: Document { title: "Spec v1", tags: ["draft"] }
copy: Document { title: "Spec v2", tags: ["draft", "published"] }
Reusing Existing Heap Capacity with .clone_from(&source)
When you want to overwrite an existing String or Vec<T> variable dest with a clone of source:
- Writing
dest = source.clone();allocates a new heap buffer forsource.clone()and freesdest's old heap buffer. - Calling
dest.clone_from(&source);reusesdest's existing heap buffer capacity if it is already large enough (dest.capacity() >= source.len()), copying the bytes in place with zero new heap allocations!
fn main() {
let mut reusable_buf = String::with_capacity(64);
let ptr_initial = reusable_buf.as_ptr();
let incoming = String::from("Copied into existing capacity without reallocating!");
reusable_buf.clone_from(&incoming);
assert_eq!(ptr_initial, reusable_buf.as_ptr());
println!("reusable_buf: '{reusable_buf}' (same heap address: {ptr_initial:p})");
}
reusable_buf: 'Copied into existing capacity without reallocating!' (same heap address: 0x600002904000)