Я простой программист. Переменные-члены моего класса чаще всего состоят из POD-типов и STL-контейнеров. Из-за этого мне редко приходится писать операторы присваивания или конструкторы копирования, поскольку они реализованы по умолчанию.
Добавьте к этому, если я использую std::move
для объектов, которые нельзя перемещать, он использует оператор присваивания, что означает std::move
совершенно безопасно.
Поскольку я простой программист, я бы хотел воспользоваться возможностями перемещения, не добавляя конструктор перемещения / оператор присваивания к каждому написанному мной классу, поскольку компилятор мог бы просто реализовать их как " this->member1_ = std::move(other.member1_);...
"
Но это не так (по крайней мере, в Visual 2010), есть ли для этого особая причина?
Важнее; есть ли способ обойти это?
Обновление: если вы посмотрите на ответ GManNickG, он предоставляет отличный макрос для этого. И если вы не знали, если вы реализуете семантику перемещения, вы можете удалить функцию-член подкачки.
источник
MyClass::MyClass(Myclass &&) = default;
?Ответы:
Неявное поколение хода конструкторов и операторы присваивания было спорным и произошло значительные изменения в последних проектах стандарта C ++, поэтому в настоящее время доступных компиляторы, вероятно, ведут себя по-разному по отношению к неявному поколению.
Чтобы узнать больше об истории проблемы, см. Список статей WG21 2010 г. и выполните поиск по запросу "mov"
Текущая спецификация (N3225, от ноября) гласит (N3225 12.8 / 8):
В 12.8 / 22 есть аналогичный язык, определяющий, когда оператор присваивания перемещения неявно объявляется как заданный по умолчанию. Вы можете найти полный список изменений, внесенных для поддержки текущей спецификации неявной генерации ходов в N3203: Ужесточение условий для генерации неявных ходов , которое было основано в основном на одном из решений, предложенных в статье Бьярна Страуструпа N3201: Движение вперед .
источник
cannot be defaulted *in the class body*
. Итак, я определил деструктор снаружи, и он сработал :). Хотя мне это кажется немного странным. У кого-нибудь есть объяснение? Компилятор - gcc 4.6.1virtual ~D() = default;
должно работать и по-прежнему допускать неявный конструктор перемещения.Неявно сгенерированные конструкторы перемещения рассматриваются в качестве стандарта, но могут быть опасными. См. Анализ Дэйва Абрахамса .
В конце концов, однако, стандарт действительно включал неявную генерацию конструкторов перемещения и операторов присваивания перемещения, хотя и с довольно существенным списком ограничений:
Однако это еще не все, что касается истории. Ctor можно объявить, но все же определить как удаленный:
источник
Tweak2
. Я полагаю, это как-то связано с тем фактом, чтоNumber
объект будет перемещен, аvector
объект будет скопирован ... но я не уверен: / Я понимаю, что проблема передается каскадомTweak3
.Да, я тоже пошел по этому пути. Вот ваш макрос:
// detail/move_default.hpp #ifndef UTILITY_DETAIL_MOVE_DEFAULT_HPP #define UTILITY_DETAIL_MOVE_DEFAULT_HPP #include <boost/preprocessor.hpp> #define UTILITY_MOVE_DEFAULT_DETAIL_CONSTRUCTOR_BASE(pR, pData, pBase) pBase(std::move(pOther)) #define UTILITY_MOVE_DEFAULT_DETAIL_ASSIGNMENT_BASE(pR, pData, pBase) pBase::operator=(std::move(pOther)); #define UTILITY_MOVE_DEFAULT_DETAIL_CONSTRUCTOR(pR, pData, pMember) pMember(std::move(pOther.pMember)) #define UTILITY_MOVE_DEFAULT_DETAIL_ASSIGNMENT(pR, pData, pMember) pMember = std::move(pOther.pMember); #define UTILITY_MOVE_DEFAULT_DETAIL(pT, pBases, pMembers) \ pT(pT&& pOther) : \ BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM( \ UTILITY_MOVE_DEFAULT_DETAIL_CONSTRUCTOR_BASE, BOOST_PP_EMPTY, pBases)) \ , \ BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM( \ UTILITY_MOVE_DEFAULT_DETAIL_CONSTRUCTOR, BOOST_PP_EMPTY, pMembers)) \ {} \ \ pT& operator=(pT&& pOther) \ { \ BOOST_PP_SEQ_FOR_EACH(UTILITY_MOVE_DEFAULT_DETAIL_ASSIGNMENT_BASE, BOOST_PP_EMPTY, pBases) \ BOOST_PP_SEQ_FOR_EACH(UTILITY_MOVE_DEFAULT_DETAIL_ASSIGNMENT, BOOST_PP_EMPTY, pMembers) \ \ return *this; \ } #define UTILITY_MOVE_DEFAULT_BASES_DETAIL(pT, pBases) \ pT(pT&& pOther) : \ BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM( \ UTILITY_MOVE_DEFAULT_DETAIL_CONSTRUCTOR_BASE, BOOST_PP_EMPTY, pBases)) \ {} \ \ pT& operator=(pT&& pOther) \ { \ BOOST_PP_SEQ_FOR_EACH(UTILITY_MOVE_DEFAULT_DETAIL_ASSIGNMENT_BASE, BOOST_PP_EMPTY, pBases) \ \ return *this; \ } #define UTILITY_MOVE_DEFAULT_MEMBERS_DETAIL(pT, pMembers) \ pT(pT&& pOther) : \ BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM( \ UTILITY_MOVE_DEFAULT_DETAIL_CONSTRUCTOR, BOOST_PP_EMPTY, pMembers)) \ {} \ \ pT& operator=(pT&& pOther) \ { \ BOOST_PP_SEQ_FOR_EACH(UTILITY_MOVE_DEFAULT_DETAIL_ASSIGNMENT, BOOST_PP_EMPTY, pMembers) \ \ return *this; \ } #endif
Взаимодействие с другими людьми
// 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
(Я удалил настоящие комментарии, длинные и документальные.)
Вы указываете базы и / или члены в своем классе как список препроцессора, например:
#include "move_default.hpp" struct foo { UTILITY_MOVE_DEFAULT_MEMBERS(foo, (x)(str)); int x; std::string str; }; struct bar : foo, baz { UTILITY_MOVE_DEFAULT_BASES(bar, (foo)(baz)); }; struct baz : bar { UTILITY_MOVE_DEFAULT(baz, (bar), (ptr)); void* ptr; };
И выходит конструктор перемещения и оператор присваивания перемещения.
(Кстати, если кто-нибудь знает, как я могу объединить детали в один макрос, это было бы здорово.)
источник
VS2010 этого не делает, потому что на момент реализации они не были стандартными.
источник