Copiar y clonar
Aunque la semántica de movimiento es la opción predeterminada, algunos tipos se copian de forma predeterminada:
fn main() { let x = 42; let y = x; println!("x: {x}"); println!("y: {y}"); }
Estos tipos implementan el trait Copy
.
Puedes habilitar tus propios tipos para que usen la semántica de copia:
#[derive(Copy, Clone, Debug)] struct Point(i32, i32); fn main() { let p1 = Point(3, 4); let p2 = p1; println!("p1: {p1:?}"); println!("p2: {p2:?}"); }
- Después de la asignación, tanto
p1
comop2
tienen sus propios datos. - También podemos utilizar
p1.clone()
para copiar los datos de forma explícita.
Copiar y clonar no es lo mismo:
- Copiar hace referencia a las copias bit a bit de regiones de memoria y no funciona en cualquier objeto.
- Copiar no permite lógica personalizada (a diferencia de los constructores de copias de C++).
- Clonar es una operación más general y que permite un comportamiento personalizado implementando el trait
Clone
. - Copiar no funciona en los tipos que implementan el trait
Drop
.
En el ejemplo anterior, prueba lo siguiente:
- Añade un campo
String
astruct Point
. No se compilará porqueString
no es de tipoCopy
. - Elimina
Copy
del atributoderive
. El error del compilador se encuentra ahora enprintln!
parap1
. - Demuestra que funciona si clonas
p1
.
Si los alumnos preguntan por derive
, basta con decir que se trata de una forma de generar código en Rust durante el tiempo de compilación. En este caso, se generan las implementaciones predeterminadas de los traits Copy
y Clone
.