Конструкторы перемещения и присваивание перемещением
Корректно реализуйте конструкторы перемещения и операторы присваивания перемещением.
«Конструкторы перемещения и присваивание перемещением» — бесплатный урок C++ Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C++ Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C++ Academy содержит 4 уроков всего.
Два специальных метода-члена
Конструктор перемещения и оператор присваивания с перемещением позволяют вашему классу забрать ресурсы другого экземпляра без копирования.
Сигнатура
Оба принимают ссылку на правостороннее значение того же типа.
class String {
public:
String(String&& other) noexcept; // move ctor
String& operator=(String&& other) noexcept; // move assign
};Реализация конструктора перемещения
Заберите ресурсы исходного объекта и оставьте его в допустимом пустом состоянии.
String(String&& other) noexcept
: data_(other.data_), size_(other.size_) {
other.data_ = nullptr;
other.size_ = 0;
}Реализация присваивания с перемещением
Три шага: освободите текущие ресурсы, заберите ресурсы исходного объекта и оставьте исходный объект пустым.
String& operator=(String&& other) noexcept {
if (this != &other) {
delete[] data_;
data_ = other.data_;
size_ = other.size_;
other.data_ = nullptr;
other.size_ = 0;
}
return *this;
}Почему важен noexcept
По возможности помечайте операции перемещения как noexcept. Стандартные контейнеры, такие как std::vector, используют перемещение при изменении размера только в том случае, если оно не может завершиться исключением; иначе для безопасности при исключениях они переходят к копированию.
Правило пяти
Если вы определяете любой из этих пяти элементов, подумайте обо всех пяти:
- Деструктор
- Конструктор копирования
- Присваивание копированием
- Конструктор перемещения
- Присваивание с перемещением
Правило нуля
Ещё лучше — не определяйте ни одного из них. Храните поля как типы RAII (векторы, строки, интеллектуальные указатели). Сгенерированные компилятором методы по умолчанию работают корректно и эффективно.
class Widget {
std::string name_;
std::vector<int> data_;
// No need for destructor, copy, or move — compiler does the right thing
};Когда компилятор генерирует перемещения
Компилятор генерирует перемещающие функции-члены по умолчанию только если:
- Пользователь не объявил конструктор копирования, оператор присваивания копированием, деструктор или перемещающие функции-члены
- Все члены и базовые классы сами поддерживают перемещение
Перемещения, заданные по умолчанию и удалённые
Вы можете явно запросить или запретить перемещения, сгенерированные компилятором.
class Widget {
public:
Widget(Widget&&) = default;
Widget& operator=(Widget&&) = default;
// or
Widget(Widget&&) = delete;
};После перемещения
Перемещённый объект находится в состоянии допустимом, но неопределённом. Вы можете:
- Уничтожить его
- Присвоить ему новое значение
- Вызвать любую операцию без предварительных условий (
size(),empty(),clear())
Варианты использования
Семантика перемещения ускоряет:
- Возврат больших объектов (если RVO не срабатывает)
- Помещение больших объектов в контейнеры (при использовании push_back для rvalue-значений)
- Реализацию собственных типов, владеющих ресурсами
Быстрая проверка
Почему конструкторы перемещения и операторы присваивания перемещением следует помечать как noexcept?
Итоги
Конструкторы перемещения и операторы присваивания перемещением забирают ресурсы у rvalue-значения, которое скоро будет уничтожено. Помечайте их как noexcept, чтобы ускорить работу контейнеров. Следуйте Правилу пяти или, что ещё лучше, Правилу нуля, комбинируя стандартные типы RAII.
Часто задаваемые вопросы
Урок «Конструкторы перемещения и присваивание перемещением» бесплатный?
Да — полный текст урока «Конструкторы перемещения и присваивание перемещением» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C++ Academy, подпишись на CoddyKit PRO. Курс C++ Academy содержит 4 уроков всего.
Чему я научусь в уроке «Конструкторы перемещения и присваивание перемещением»?
Корректно реализуйте конструкторы перемещения и операторы присваивания перемещением. Ты практикуешь C++ Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать C++ Academy?
Предыдущий опыт не требуется. C++ Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.
Сколько времени занимает урок «Конструкторы перемещения и присваивание перемещением»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке C++ Academy?
Да. Каждый урок C++ Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Lvalue и rvalue: различие
- Ссылки rvalue и синтаксис &&
- std::move и std::forward
- Конструкторы перемещения и присваивание перемещением