Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Копируемые типы

Хотя семантика перемещения используется по умолчанию, некоторые типы копируются по умолчанию:

// 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.