Copy în Rust

Trait marker pentru tipurile copiate automat bit cu bit la atribuire, în loc să fie mutate (numere, char, bool...).

Sintaxă
#[derive(Clone, Copy)]
struct Punct { x: i32, y: i32 }

pub trait Copy: Clone { }

Ce face Copy

Pentru un tip Copy, let b = a; face o copie, iar a rămâne utilizabil. Așa se comportă toate numerele, bool, char, referințele &T și tuplurile sau tablourile formate doar din tipuri Copy. Copia este ieftină și implicită: nu scrii .clone().

Un tip propriu devine Copy cu #[derive(Clone, Copy)] (Clone este obligatoriu alături). Se poate doar dacă toate câmpurile sunt Copy: o structură cu String, Vec sau Box nu poate fi Copy, pentru că acele tipuri dețin memorie pe heap. Nici tipurile care implementează Drop nu pot fi Copy.

Copy nu are metode. Implementarea manuală este impl Copy for Tip {}, împreună cu un Clone care returnează *self.

Ce returnează

Nu are metode; schimbă doar comportamentul atribuirii și al transmiterii prin valoare.

Exemple

Exemplul 1: Copiere implicită pentru un tip mic

#[derive(Clone, Copy)]
struct Punct {
    x: i32,
    y: i32,
}

fn muta(mut p: Punct, dx: i32) -> Punct {
    p.x += dx;
    p
}

fn main() {
    let a = Punct { x: 1, y: 2 };
    let b = a;              // copie, nu mutare
    let c = muta(a, 10);    // a este copiat în funcție
    println!("a = ({}, {})", a.x, a.y);
    println!("b = ({}, {})", b.x, b.y);
    println!("c = ({}, {})", c.x, c.y);
}

Rezultat

a = (1, 2)
b = (1, 2)
c = (11, 2)

Exemplul 2: Implementare manuală

struct Culoare {
    r: u8,
    g: u8,
    b: u8,
}

impl Clone for Culoare {
    fn clone(&self) -> Self {
        *self
    }
}

impl Copy for Culoare {}

fn main() {
    let rosu = Culoare { r: 206, g: 17, b: 38 };
    let alt = rosu;
    println!("#{:02X}{:02X}{:02X}", rosu.r, rosu.g, rosu.b);
    println!("#{:02X}{:02X}{:02X}", alt.r, alt.g, alt.b);
}

Rezultat

#CE1126
#CE1126

Exemplul 3: Copy nu merge cu String

#[derive(Clone, Copy)]
struct Elev {
    nume: String,
    nota: u8,
}

fn main() {
    let a = Elev { nume: String::from("Ana"), nota: 10 };
    let b = a;
    println!("{} {} {}", a.nume, b.nume, b.nota);
}

Eroarea de compilare (rustc)

error[E0204]: the trait `Copy` cannot be implemented for this type
 --> main.rs:2:8
  |
1 | #[derive(Clone, Copy)]
  |                 ---- in this derive macro expansion
2 | struct Elev {
  |        ^^^^
3 |     nume: String,
  |     ------------ this field does not implement `Copy`

Greșeli frecvente

  • Scrii doar #[derive(Copy)]: Copy cere și Clone. Scrie #[derive(Clone, Copy)].
  • Faci Copy un tip mare (de exemplu un tablou de mii de elemente). Fiecare atribuire copiază tot; pentru tipuri mari mutarea sau referințele sunt mai potrivite.

Comenzi înrudite

  • Clone: Trait-ul pentru copierea explicită a unei valori cu .clone(); se obține cu #[derive(Clone)] sau implementare manuală.
  • Drop: Codul rulat automat când o valoare iese din domeniu (destructor): închidere de fișiere, eliberare de resurse, mesaje.
  • Sized: Trait marker pentru tipurile cu dimensiune cunoscută la compilare; ?Sized permite și str, [T], dyn Trait.