Rozważmy historię pytania:
W Rust koncepcja zarządzania pamięcią i posiadania wymaga wyraźnego określenia, jak obiekty są przenoszone i kopiowane. Na początku języka ważne było zróżnicowanie prostej kopii bajtów (bez alokacji i logiki) i głębokiego klonowania (na przykład, kopia łańcucha, wektora). W tym celu wprowadzono dwa trait — Copy i Clone.
Problem polega na tym, że nie wszystkie typy danych są równie tanie do kopiowania. Dla niektórych struktur kopiowanie to po prostu skopiowanie bitów (na przykład liczby całkowite lub krotki typów Copy), a dla innych (na przykład String, Vec) wiąże się z dodatkową pracą nad alokacją pamięci. Podział na Copy i Clone pozwala Rustowi zgłaszać błędy kompilacji, jeśli spróbujemy wykonać niedozwolone kopiowanie.
Rozwiązanie:
Copy są automatycznie kopiowane podczas przekazywania, przypisywania i przekazywania do funkcji. Obiekty takich typów pozostają ważne po skopiowaniu.Clone, co wymaga jawnego wywołania metody .clone(), często z dodatkową alokacją zasobów.Przykład kodu:
#[derive(Debug, Copy, Clone)] struct Point { x: i32, y: i32, } fn main() { let p1 = Point { x: 1, y: 2 }; let p2 = p1; // p1 nie staje się "nieważny" println!("{:?} {:?}", p1, p2); }
Kluczowe cechy:
Copy - automatyczne kopiowanie bitowe, nie wymaga ręcznego wywołania i nie wpływa na posiadanie.Clone - jawne głębokie kopiowanie, odpowiednie dla struktur z danymi na stercie.Czy typy z danymi alokowanymi na stercie mogą mieć pochodzenie Copy?
Nie, typy zawierające dane na stercie (na przykład String, Vec) nie mogą automatycznie realizować Copy, gdyż prowadzi to do podwójnego zwolnienia pamięci.
Jeśli typ implementuje Copy, czy można również zaimplementować Clone ręcznie z inną logiką?
Tak, Clone można zaimplementować ręcznie, a logika może się różnić, jednak zaleca się, aby Copy i Clone były zgodne: Copy po prostu wywołuje Clone bez alokacji.
#[derive(Copy)] struct X; impl Clone for X { fn clone(&self) -> X { *self } }
Jeśli struktura zawiera tylko pola Copy, ale nie jest oznaczona #[derive(Copy)], czy będzie Copy?
Nie, typ nie staje się Copy automatycznie z powodu składu — wymagana jest jawna derivacja Copy dla twojego typu.
Typ z danymi na stercie błędnie oznaczony jako Copy, prowadzi do podwójnego zwolnienia pamięci podczas finalizacji.
Zalety:
Wady:
Użycie Copy dla lekkich struktur (końcówki, kolory), Clone — dla bardziej złożonych (łańcuchy, wektory). Kod jest bezpieczny i przewidywalny.
Zalety:
Wady: