Copy and Clone in Rust: What's the Difference and Which to Choose?

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction: Why Copy and Clone Are Not the Same Thing?

\n\n

Everyone who starts learning Rust eventually encounters two mysterious traits: Copy and Clone. At first glance, they do the same thing — allow you to get a duplicate of a value. But the devil, as always, is in the details.

\n\n

Imagine you are writing a program and passing a value to a function. In C++, that would be copying (or moving, if you're lucky). In Python, it's just another reference to the object. But in Rust... Rust forces you to explicitly decide: "I want this value to be copied" or "I want to clone it with an awareness of the cost."

\n\n

This is precisely where the boundary between Copy and Clone lies. The former is a "lightweight bit-by-bit copy." The latter is a "conscious, potentially expensive duplication."

\n\n

Let's figure out with examples when and what to use so that your Rust code is not only correct but also efficient.

\n\n

Quick Overview: Copy vs Clone

\n\n

What is Clone?

\n\n

Clone is a trait that provides you with the .clone() method. By calling it, you explicitly tell the compiler: "I know this might be expensive, but I need an independent copy."

\n\n

Features of Clone:

\n
    \n
  • Can be implemented for any type
  • \n
  • Requires an explicit call to .clone()
  • \n
  • Can perform deep copying (e.g., for Vec or String)
  • \n
  • Does not change ownership semantics — after cloning, you have two independent values
  • \n
\n\n

What is Copy?

\n\n

Copy is a "marker" trait (no methods). If a type implements Copy, the compiler can simply copy its bits upon assignment or passing to a function. This does not require calling .clone().

\n\n

Features of Copy:

\n
    \n
  • Works only for simple types that can be safely copied bitwise
  • \n
  • Does not require an explicit call — copying happens automatically
  • \n
  • The type must still implement Clone (it is a supertrait)
  • \n
  • The original value remains valid after copying
  • \n
\n\n

Practical Examples: How It Works in Code

\n\n

Example 1: Basic Types (Copy)

\n\n

Integers, floating-point numbers, boolean values — all implement Copy:

\n\n
fn main() {\n    let x = 42;\n    let y = x; // x is copied to y, x is still available\n    \n    println!("x = {}, y = {}", x, y); // Works!\n}
\n\n

Here, x is an i32, which implements Copy. Therefore, when assigning y = x, copying occurs, and x remains valid.

\n\n

Example 2: String (Clone only)

\n\n

But String is a complex type that stores data on the heap. It implements Clone, but not Copy:

\n\n
fn main() {\n    let s1 = String::from("Hello, Rust!");\n    let s2 = s1; // s1 is moved to s2\n    \n    // println!("{}", s1); // Error! s1 no longer owns the data\n    \n    let s3 = s2.clone(); // This is allowed — explicit cloning\n    println!("s2 = {}, s3 = {}", s2, s3); // Works!\n}
\n\n

Why can't String be Copy? Because a bitwise copy of String would result in two pointers to the same heap memory. When both values are dropped — double free. Clone, on the other hand, creates a fully independent copy.

\n\n

Example 3: Custom Type with Copy

\n\n

You can make your type Copy if it consists only of Copy types:

\n\n
#[derive(Debug, Copy, Clone)]\nstruct Point {\n    x: f64,\n    y: f64,\n}\n\nfn main() {\n    let p1 = Point { x: 1.0, y: 2.0 };\n    let p2 = p1; // Copied, p1 remains\n    \n    println!                

Blogs

Book Recommendations