Трейт Copy
Трейт Copy помечает типы, значения которых
можно копировать простым побитовым копированием
памяти. Когда тип реализует Copy, присваивание
переменной, передача в функцию или возврат из
функции создают независимую копию значения, а
не перемещают владение. Это означает, что после
копирования исходная переменная остаётся
доступной для дальнейшего использования.
Трейт не содержит методов и служит маркером.
Тип может реализовать Copy только в том
случае, если все его поля также реализуют
Copy. Кроме того, тип, реализующий
Copy, обязан также реализовать трейт
Clone. Многие примитивные типы, такие как
i32, f64, bool и char,
уже реализуют Copy.
Синтаксис
#[derive(Copy, Clone)]
struct MyStruct
{
field: i32,
}
Также трейт можно реализовать вручную:
impl Copy for MyStruct
{
}
impl Clone for MyStruct
{
fn clone(&self) -> Self
{
*self
}
}
Пример
Давайте создадим структуру, реализующую
Copy, и проверим, что после присваивания
исходная переменная остаётся доступной:
#[derive(Copy, Clone, Debug)]
struct Point
{
x: i32,
y: i32,
}
fn main()
{
let p1 = Point { x: 1, y: 2 };
let p2 = p1;
println!("{:?}", p1);
println!("{:?}", p2);
}
Результат выполнения кода:
Point { x: 1, y: 2 }
Point { x: 1, y: 2 }
Пример
Давайте сравним поведение типа с Copy и
типа без него. Сначала тип без Copy:
#[derive(Debug)]
struct NotCopy
{
value: i32,
}
fn main()
{
let a = NotCopy { value: 10 };
let b = a;
println!("{:?}", b);
}
Результат выполнения кода:
NotCopy { value: 10 }
После присваивания let b = a; переменная
a перемещается, и попытка её использовать
приведёт к ошибке компиляции. Если же добавить
Copy, такой проблемы не возникнет.
Пример
Давайте передадим значение типа с Copy
в функцию и убедимся, что исходная переменная
по-прежнему доступна:
#[derive(Copy, Clone, Debug)]
struct Pair
{
a: i32,
b: i32,
}
fn print_pair(p: Pair)
{
println!("{:?}", p);
}
fn main()
{
let pair = Pair { a: 1, b: 2 };
print_pair(pair);
println!("{:?}", pair);
}
Результат выполнения кода:
Pair { a: 1, b: 2 }
Pair { a: 1, b: 2 }