Копируемые типы
Хотя семантика перемещения используется по умолчанию, некоторые типы копируются по умолчанию:
// Copyright 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0
fn main() {
let x = 42;
let y = x;
dbg!(x); // would not be accessible if not Copy
dbg!(y);
}
Эти типы реализуют трейт Copy.
Свои типы можно явно пометить для использования семантики копирования:
// Copyright 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0
#[derive(Copy, Clone, Debug)]
struct Point(i32, i32);
fn main() {
let p1 = Point(3, 4);
let p2 = p1;
println!("p1: {p1:?}");
println!("p2: {p2:?}");
}
- После присваивания и
p1, иp2владеют собственными данными. - Также можно использовать
p1.clone(), чтобы явно скопировать данные.
This slide should take about 5 minutes.
Копирование и клонирование — не одно и то же:
- Копирование означает побитовое копирование областей памяти и не работает для произвольных объектов.
- Копирование не позволяет выполнять произвольную логику (в отличие от конструкторов копирования в C++).
- Клонирование — более общая операция, которая также позволяет задать собственное поведение, реализовав трейт
Clone. - Копирование не работает для типов, которые реализуют трейт
Drop.
В приведённом выше примере попробуйте следующее:
- Добавьте поле
Stringвstruct Point. Код не скомпилируется, потому чтоStringне является типомCopy. - Удалите
Copyиз атрибутаderive. Ошибка компилятора теперь будет вprintln!дляp1. - Покажите, что код работает, если вместо этого клонировать
p1.
Для дальнейшего изучения
- Разделяемые ссылки реализуют
Copy/Clone, а изменяемые — нет. Это потому, что Rust требует, чтобы изменяемые ссылки были эксклюзивными: хотя копия разделяемой ссылки допустима, создание копии изменяемой ссылки нарушило бы правила заимствования Rust.