Ownership

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 for source.clone() and frees dest's old heap buffer.
  • Calling dest.clone_from(&source); reuses dest'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)