Copy e Clone em Rust: qual a diferença e o que escolher?

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução: por que Copy e Clone não são a mesma coisa?

\n\n

Todo mundo que começa a estudar Rust, mais cedo ou mais tarde, se depara com duas traits misteriosas: Copy e Clone. À primeira vista, elas fazem a mesma coisa — permitem obter uma duplicata de um valor. Mas o diabo, como sempre, está nos detalhes.

\n\n

Imagine que você está escrevendo um programa e passando um valor para uma função. Em C++, isso seria uma cópia (ou uma movimentação, se tivesse sorte). Em Python — apenas mais uma referência ao objeto. E em Rust... Rust obriga você a decidir explicitamente: "Eu quero que este valor seja copiado" ou "Eu quero cloná-lo com consciência dos custos".

\n\n

É aqui que passa a fronteira entre Copy e Clone. O primeiro é uma "cópia leve, bit a bit". O segundo é uma "duplicação consciente, possivelmente cara".

\n\n

Vamos entender com exemplos quando e o que usar, para que seu código em Rust seja não apenas correto, mas também eficiente.

\n\n

Resumindo: Copy vs Clone

\n\n

O que é Clone?

\n\n

Clone é uma trait que fornece o método .clone(). Ao chamá-lo, você diz explicitamente ao compilador: "Eu sei que isso pode ser caro, mas preciso de uma cópia independente".

\n\n

Características do Clone:

\n
    \n
  • Pode ser implementado para qualquer tipo
  • \n
  • Requer chamada explícita de .clone()
  • \n
  • Pode realizar cópia profunda (por exemplo, para Vec ou String)
  • \n
  • Não altera a semântica de posse — após a clonagem, você tem dois valores independentes
  • \n
\n\n

O que é Copy?

\n\n

Copy é uma trait "marcadora" (sem métodos). Se um tipo implementa Copy, o compilador pode simplesmente copiar seus bits ao atribuir ou passar para uma função. Isso não requer chamar .clone().

\n\n

Características do Copy:

\n
    \n
  • Funciona apenas para tipos simples que podem ser copiados com segurança bit a bit
  • \n
  • Não requer chamada explícita — a cópia ocorre automaticamente
  • \n
  • O tipo ainda deve implementar Clone (é uma supertrait)
  • \n
  • O valor original permanece válido após a cópia
  • \n
\n\n

Exemplos práticos: como funciona no código

\n\n

Exemplo 1: Tipos básicos (Copy)

\n\n

Inteiros, números de ponto flutuante, valores booleanos — todos implementam Copy:

\n\n
fn main() {\n    let x = 42;\n    let y = x; // x é copiado para y, x ainda está disponível\n    \n    println!("x = {}, y = {}", x, y); // Funciona!\n}
\n\n

Aqui, x é um i32, que implementa Copy. Portanto, ao atribuir y = x, ocorre uma cópia, e x permanece válido.

\n\n

Exemplo 2: String (apenas Clone)

\n\n

Já String é um tipo complexo que armazena dados no heap. Ele implementa Clone, mas não Copy:

\n\n
fn main() {\n    let s1 = String::from("Olá, Rust!");\n    let s2 = s1; // s1 é movido para s2\n    \n    // println!("{}", s1); // Erro! s1 não possui mais os dados\n    \n    let s3 = s2.clone(); // Assim funciona — clonagem explícita\n    println!("s2 = {}, s3 = {}", s2, s3); // Funciona!\n}
\n\n

Por que String não pode ser Copy? Porque copiar bit a bit uma String resultaria em dois ponteiros para a mesma memória no heap. Ao fazer drop de ambos os valores — liberação dupla de memória. Já Clone cria uma cópia independente completa.

\n\n

Exemplo 3: Tipo próprio com Copy

\n\n

Você pode tornar seu tipo Copy se ele for composto apenas por tipos Copy:

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

Blogs

Book Recommendations