Copia e Clonagem

Embora a semântica de movimento seja o padrão, certos tipos são copiados por padrão:

fn main() {
    let x = 42;
    let y = x;
    println!("x: {x}");
    println!("y: {y}");
}

Esses tipos implementam o trait Copy.

Você pode habilitar seus próprios tipos para usar a semântica de cópia:

#[derive(Copy, Clone, Debug)]
struct Point(i32, i32);

fn main() {
    let p1 = Point(3, 4);
    let p2 = p1;
    println!("p1: {p1:?}");
    println!("p2: {p2:?}");
}
  • Após a atribuição, tanto p1 quanto p2 possuem seus próprios dados.
  • Também podemos usar p1.clone() para copiar os dados explicitamente.

Copia e clonagem não são a mesma coisa:

  • Cópia refere-se a cópias bit a bit de regiões de memória e não funciona em objetos arbitrários.
  • Cópia não permite lógica personalizada (ao contrário dos construtores de cópia em C++).
  • Clonagem é uma operação mais geral e também permite um comportamento personalizado através da implementação do trait Clone.
  • Cópia não funciona em tipos que implementam o trait Drop.

No exemplo acima, tente o seguinte:

  • Adicione um campo String ao struct Point. Ele não irá compilar porque String não é um tipo Copy.
  • Remova Copy do atributo derive. O erro do compilador agora está no println! para p1.
  • Mostre que ele funciona se ao invés disso você clonar p1.

Se os alunos perguntarem sobre derive, basta dizer que isto é uma forma de gerar código em Rust em tempo de compilação. Nesse caso, as implementações padrão dos traits Copy e Clone são geradas.