En Rust, la gestión de la memoria y la semántica de propiedad (ownership) dictan cómo se duplican los datos. El trait Clone permite realizar una duplicación explícita de un objeto, lo cual puede ser una operación costosa si implica la asignación de memoria en el heap (como ocurre con String). Por el contrario, el trait Copy indica que un tipo puede ser duplicado mediante una copia bit a bit (bitwise copy) sin alterar la semántica de movimiento. Los tipos que contienen punteros a datos en el heap no pueden implementar Copy, ya que duplicar solo los bits del puntero resultaría en dos dueños de la misma dirección de memoria, violando las reglas de seguridad de Rust.
Para la comparación, Rust utiliza una jerarquía de traits. PartialEq permite el uso de los operadores == y !=. Se denomina “parcial” porque no garantiza la reflexividad; por ejemplo, en los tipos de punto flotante (f64), NaN != NaN, por lo que la igualdad no es total. Eq es un marker trait que hereda de PartialEq y se utiliza cuando se garantiza la reflexividad (si $a = b$, entonces $b = a$ y $a = a$).
En cuanto al orden, PartialOrd habilita los operadores de comparación (<, >, <=, >=) y su implementación de partial_cmp devuelve un Option<Ordering>, permitiendo que la comparación falle (como con NaN). El trait Ord requiere que el tipo implemente Eq y proporciona un ordenamiento total, donde cmp siempre devuelve un Ordering definido, eliminando la posibilidad de resultados indefinidos.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
struct Coordenada {
x: i32,
y: i32,
}
#[derive(Clone, PartialEq, Debug)]
struct Usuario(String);
fn main() {
// Ejemplo de Copy: La asignación no mueve, copia bits.
let c1 = Coordenada { x: 10, y: 20 };
let c2 = c1;
println!("c1: {:?}, c2: {:?}", c1, c2); // c1 sigue siendo válido gracias a Copy
// Ejemplo de Clone: Duplicación explícita para tipos en el heap.
let u1 = Usuario(String::from("Alice"));
let u2 = u1.clone();
println!("u1: {:?}, u2: {:?}", u1, u2); // u1 es válido porque clonamos la String
// Ejemplo de comparación (Ord)
let c3 = Coordenada { x: 10, y: 25 };
if c1 < c3 {
println!("c1 es menor que c3");
}
}
Explicación del Código
Coordenada: Esta estructura utiliza#[derive(...)]para implementar automáticamenteClone,Copy,PartialEq,Eq,PartialOrdyOrd. Esto es posible porque sus campos (i32) implementan todos estos rasgos.Usuario: Solo implementaCloneyPartialEq. No implementaCopyporque contiene unString, el cual es un tipo que gestiona memoria en el heap.c1yc2: Debido a queCoordenadaimplementaCopy, la asignaciónlet c2 = c1;realiza una copia bit a bit en el stack. Esto permite quec1siga siendo accesible después de la asignación, a diferencia de los tipos que solo implementanClone.u1yu2:u1es de tipoUsuario. Al llamar au1.clone(), se ejecuta una copia profunda de laStringinterna, creando una nueva asignación en el heap parau2.c1 < c3: Esta comparación utiliza el traitPartialOrd(derivado deOrd). Dado queCoordenadaimplementaOrd, la comparación es total y segura, evaluando primero el campoxy, en caso de empate, el campoy.
N° 48