Consideremos la historia de la pregunta:
En Rust, el concepto de gestión de memoria y propiedad exige una definición clara de cómo los objetos se mueven y se copian. En los inicios del lenguaje, era importante distinguir entre la simple copia de bytes (sin asignaciones ni lógica) y la clonación profunda (por ejemplo, una copia de una cadena, un vector). Para ello se introdujeron dos traits: Copy y Clone.
El problema es que no todos los tipos de datos se copian de la misma manera eficiente. Para algunas estructuras, copiar es simplemente copiar bits (por ejemplo, enteros o tuplas de tipos Copy), mientras que para otros (por ejemplo, String, Vec) se requiere trabajo adicional de asignación de memoria. La separación de Copy y Clone permite que Rust emita un error de compilación si se intenta realizar una copia inválida.
Solución:
Copy se copian automáticamente al ser transferidos, asignados o pasados a funciones. Los objetos de estos tipos permanecen válidos después de la copia.Clone, que requiere la llamada explícita al método .clone(), a menudo con asignación adicional de recursos.Ejemplo de código:
#[derive(Debug, Copy, Clone)] struct Point { x: i32, y: i32, } fn main() { let p1 = Point { x: 1, y: 2 }; let p2 = p1; // p1 no se vuelve "inválido" println!("{:?} {:?}", p1, p2); }
Características clave:
Copy - copia binaria automática, no requiere llamada manual y no afecta la propiedad.Clone - copia profunda explícita, adecuada para estructuras con datos en heap.¿Pueden los tipos con datos asignados en heap tener derivación Copy?
No, los tipos que contienen datos en heap (por ejemplo, String, Vec) no pueden implementar automáticamente Copy, ya que esto resultaría en una doble liberación de memoria.
Si un tipo implementa Copy, ¿se puede implementar Clone manualmente con otra lógica?
Sí, Clone se puede implementar manualmente y la lógica puede diferir, sin embargo, se recomienda que Copy y Clone sean coherentes: Copy simplemente llama a Clone sin asignaciones.
#[derive(Copy)] struct X; impl Clone for X { fn clone(&self) -> X { *self } }
Si una estructura contiene solo campos Copy, pero no está marcada con #[derive(Copy)], ¿será Copy?
No, un tipo no se convierte en Copy automáticamente por su composición: se requiere una derivación explícita de Copy para su tipo.
Un tipo con datos en heap marcado incorrectamente como Copy resulta en una doble liberación de memoria durante la finalización.
Ventajas:
Desventajas:
Uso de Copy para estructuras ligeras (coordenadas, colores), Clone para complejas (cadenas, vectores). El código es seguro y predecible.
Ventajas:
Desventajas: