Saltar al contenido

¿Cuál es la diferencia entre Copiar y Clonar?

No olvides que en la informática un error puede tener diferentes soluciones, no obstante mostramos lo más óptimo y eficiente.

Solución:

Clone está diseñado para duplicaciones arbitrarias: un Clone implementación para un tipo T puede hacer operaciones arbitrariamente complicadas requeridas para crear un nuevo T. Es un rasgo normal (aparte de estar en el preludio), por lo que requiere ser usado como un rasgo normal, con llamadas a métodos, etc.

los Copy El rasgo representa valores que se pueden duplicar de forma segura a través de memcpy: cosas como reasignaciones y pasar un argumento por valor a una función siempre son memcpys, y así para Copy tipos, el compilador entiende que no necesita considerarlos como un movimiento.

La principal diferencia es que la clonación es explícita. La notación implícita significa mover para un no-Copy escribe.

// u8 implements Copy
let x: u8 = 123;
let y = x;
// x can still be used
println!("x=, y=", x, y);

// Vec implements Clone, but not Copy
let v: Vec = vec![1, 2, 3];
let w = v.clone();
//let w = v // This would *move* the value, rendering v unusable.

Por cierto, cada Copy También se requiere que el tipo sea Clone. Sin embargo, ¡no están obligados a hacer lo mismo! Para sus propios tipos, .clone() puede ser un método arbitrario de su elección, mientras que la copia implícita siempre activará un memcpyno la clone(&self) implementación.

Como ya está cubierto por otras respuestas:

  • Copy es implícito, económico y no se puede volver a implementar (memcpy).
  • Clone es explícito, puede ser costoso y puede volver a implementarse arbitrariamente.

Lo que a veces falta en la discusión de Copy contra Clone es que también afecta cómo el compilador usa movimientos frente a copias automáticas. Por ejemplo:

#[derive(Debug, Clone, Copy)]
pub struct PointCloneAndCopy 
    pub x: f64,


#[derive(Debug, Clone)]
pub struct PointCloneOnly 
    pub x: f64,


fn test_copy_and_clone() 
    let p1 = PointCloneAndCopy  x: 0. ;
    let p2 = p1; // because type has `Copy`, it gets copied automatically.
    println!(":? :?", p1, p2);


fn test_clone_only() 
    let p1 = PointCloneOnly  x: 0. ;
    let p2 = p1; // because type has no `Copy`, this is a move instead.
    println!(":? :?", p1, p2);

El primer ejemplo (PointCloneAndCopy) funciona bien aquí debido a la copia implícita, pero el segundo ejemplo (PointCloneOnly) cometería un error con un uso después del movimiento:

error[E0382]: borrow of moved value: `p1`
  --> src/lib.rs:20:27
   |
18 |     let p1 = PointCloneOnly  x: 0. ;
   |         -- move occurs because `p1` has type `PointCloneOnly`, which does not implement the `Copy` trait
19 |     let p2 = p1;
   |              -- value moved here
20 |     println!(":? :?", p1, p2);
   |                           ^^ value borrowed here after move

Para evitar el movimiento implícito, podríamos llamar explícitamente let p2 = p1.clone();.

Esto puede plantear la pregunta de cómo forzar un movimiento de un tipo que implementa el rasgo Copiar. Respuesta corta: no puedes/no tiene sentido.

Comentarios y valoraciones del tutorial

Acuérdate de que tienes autorización de agregar una reseña si te ayudó.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)


Tags : /

Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *