Почему нет присваивания / конструктора перемещения по умолчанию?
Автор вопроса: Viktor SehrОтветов: 4
Я простой программист. Переменные-члены моего класса чаще всего состоят из POD-типов и STL-контейнеров. Из-за этого мне редко приходится писать операторы присваивания или конструкторы копирования, поскольку они реализованы по умолчанию.
Добавьте к этому, если я использую std::move для неподвижных объектов, он использует оператор присваивания, что означает, что std::move совершенно безопасен.
Поскольку я простой программист, я хотел бы воспользоваться возможностями перемещения, не добавляя конструктор перемещения / оператор присваивания к каждому классу, который я пишу, поскольку компилятор может просто реализовать их как "this->member1_ = std::move(other.member1_);..."
Но это не так (по крайней мере, в Visual 2010), есть ли для этого какая-то особая причина?
Важнее; есть ли способ обойти это?
Обновление:. Если вы посмотрите на ответ GManNickG, он предоставляет отличный макрос для этого. И если вы не знали, если вы реализуете семантику перемещения, вы можете удалить функцию-член подкачки.
вы знаете, что можете заставить компилятор сгенерировать ctor перемещения по умолчанию aaronman 05.09.2013
std :: move не выполняет перемещение, он просто преобразует l-значение в r-значение. Перемещение по-прежнему выполняется конструктором перемещения. Owen Delahoy 01.10.2015
Вы говорите о MyClass::MyClass(Myclass &&) = default;? Sandburg 03.09.2019
Неявная генерация конструкторов перемещения и операторов присваивания была спорной, и в последние проекты стандарта C ++ были внесены серьезные изменения, поэтому доступные в настоящее время компиляторы, вероятно, будут вести себя иначе в отношении неявной генерации.
Текущая спецификация (N3225, от ноября) гласит (N3225 12.8 / 8):
Если в определении класса X явно не объявляется конструктор перемещения, он будет неявно объявлен как конструктор по умолчанию тогда и только тогда, когда
X не имеет конструктора копирования, объявленного пользователем, и
X не имеет объявленного пользователем оператора присваивания копии,
X не имеет объявленного пользователем оператора присваивания перемещения,
X не имеет деструктора, объявленного пользователем, и
конструктор перемещения не будет неявно определен как удаленный.
В 12.8 / 22 есть аналогичный язык, определяющий, когда оператор присваивания перемещения неявно объявляется как заданный по умолчанию. Вы можете найти полный список изменений, внесенных для поддержки текущей спецификации неявной генерации перемещений, в N3203: ужесточение условий для генерации неявных ходов, которое в значительной степени основывалось на одном из решений, предложенных в статье Бьярна Страуструпа N3201: Продолжаем прямо.
Ответ 2 · рейтинг 13 · Jerry Coffin
Неявно сгенерированные конструкторы перемещения рассматриваются в качестве стандарта, но могут быть опасными. См. анализ Дэйва Абрахамса.
В конце концов, однако, стандарт включал неявную генерацию конструкторов перемещения и операторов присваивания перемещения, хотя и с довольно существенным списком ограничений:
Если определение класса X явно не объявляет конструктор перемещения, он будет неявно объявлен как конструктор по умолчанию, если и только если - X не имеет конструктора копии, объявленного пользователем, - X не имеет объявленный пользователем оператор присваивания копии, - X не имеет объявленного пользователем оператора присваивания перемещения, - X не имеет объявленного пользователем деструктора, и - конструктор перемещения не будет определяться неявно как удалено.
Однако это еще не все, что касается истории. Ctor может быть объявлен, но все же определен как удаленный:
Неявно объявленный конструктор копирования / перемещения является встроенным публичным членом своего класса. Конструктор копирования / перемещения по умолчанию для класса X определяется как удаленный (8.4.3), если X имеет:
- вариантный член с нетривиальным соответствующим конструктором, а X - класс, подобный объединению, - нестатический член данных типа M (или его массив), который не может быть скопирован / перемещен из-за разрешения перегрузки (13.3 ), применительно к соответствующему конструктору M, приводит к неоднозначности или к функции, которая удалена или недоступна из конструктора по умолчанию, - прямой или виртуальный базовый класс B, который не может быть скопирован / перемещен из-за разрешения перегрузки (13.3), применительно к соответствующему конструктору B приводит к неоднозначности или к функции, которая удалена или недоступна из конструктора по умолчанию, - любой прямой или виртуальный базовый класс или нестатический член данных типа с удаленным деструктором или недоступен из конструктора по умолчанию, - для конструктора копирования, нестатического члена данных ссылочного типа rvalue или - для конструктора перемещения, нестатического члена данных или прямого или виртуального базового класса с тип, не имеющий конструкции перемещения r и не копируется тривиально.
// move_default.hpp
#ifndef UTILITY_MOVE_DEFAULT_HPP
#define UTILITY_MOVE_DEFAULT_HPP
#include "utility/detail/move_default.hpp"
// move bases and members
#define UTILITY_MOVE_DEFAULT(pT, pBases, pMembers) UTILITY_MOVE_DEFAULT_DETAIL(pT, pBases, pMembers)
// base only version
#define UTILITY_MOVE_DEFAULT_BASES(pT, pBases) UTILITY_MOVE_DEFAULT_BASES_DETAIL(pT, pBases)
// member only version
#define UTILITY_MOVE_DEFAULT_MEMBERS(pT, pMembers) UTILITY_MOVE_DEFAULT_MEMBERS_DETAIL(pT, pMembers)
#endif
(Я удалил настоящие комментарии, длинные и документальные.)
Вы указываете базы и / или члены в своем классе как список препроцессора, например: