Рассмотрим историю вопроса:
В Rust концепция управления памятью и владения требует четкого определения того, как объекты перемещаются и копируются. На заре языка было важно различать простое копирование байтов (без аллокаций и логики) и глубокое клонирование (например, копия строки, вектора). Для этого были введены два trait — Copy и Clone.
Проблема заключается в том, что не все типы данных одинаково дешево копируются. Для некоторых структур копирование — это просто копия битов (например, целые числа или кортежи из Copy-типов), а для других (например, String, Vec) возникает дополнительная работа по аллокации памяти. Разделение Copy и Clone позволяет Rust выдавать ошибку компиляции, если попытаться сделать недопустимое копирование.
Решение:
Copy, автоматически копируются при передаче, присваивании и передаче в функции. Объекты таких типов остаются валидными после копирования.Clone, который предполагает явный вызов метода .clone(), зачастую с дополнительной аллокацией ресурсов.Пример кода:
#[derive(Debug, Copy, Clone)] struct Point { x: i32, y: i32, } fn main() { let p1 = Point { x: 1, y: 2 }; let p2 = p1; // p1 не становится "недействительным" println!("{:?} {:?}", p1, p2); }
Ключевые особенности:
Copy - автоматическое побитное копирование, не требует ручного вызова и не влияет на владение.Clone - явное глубокое копирование, подходит для структур с heap-данными.Могут ли типы с heap-аллоцированными данными иметь деривацию Copy?
Нет, типы, содержащие heap-данные (например, String, Vec), не могут автоматически реализовать Copy, так как это приведет к двойному освобождению памяти.
Если тип реализует Copy, можно ли его также реализовать Clone вручную с другой логикой?
Да, Clone можно реализовать вручную и логика может отличаться, однако рекомендуется, чтобы Copy и Clone были согласованы: Copy просто вызывает Clone без аллокаций.
#[derive(Copy)] struct X; impl Clone for X { fn clone(&self) -> X { *self } }
Если структура содержит только Copy-поля, но не помечена #[derive(Copy)], будет ли она Copy?
Нет, тип не становится Copy автоматически из-за состава — требуется явная деривация Copy для вашего типа.
Тип с heap-данными ошибочно помечен как Copy, происходит двойное освобождение памяти при финализации.
Плюсы:
Минусы:
Использование Copy для легких структур (координаты, цвета), Clone — для сложных (строки, вектора). Код безопасен и предсказуем.
Плюсы:
Минусы: