Неявно объявленные операции перемещения не возвращаются к копированию?

Правильно ли я прочитал N3291 "12.8.(15/11/28) Копирование и перемещение объектов класса class.copy]", что неявно объявленный конструктор перемещения

  • выполняет поэлементное перемещение всех нестатических членов данных (вероятно, через соответственно определенные T(T&&)
  • и если какой-либо нестатический член данных не может быть перемещен, неявный конструктор перемещения будет помечен как удаленный и не будет пытаться быть скопированным в качестве «запасного варианта»? (да, перемещение определено для встроенных типов, но на самом деле является копией).

а также переместить-назначить, используя соответствующие T operator=(T&&) элементов.

Пример:

struct CopyOnly {
    CopyOnly();
    CopyOnly(const CopyOnly&);
}; // declaring a copy means no implicit move.

struct Question {
    std::vector<int> data_;
    CopyOnly         copyOnly_;
};

Класс Question

  • будет иметь неявно объявленный copy-constructor и assign
  • будут иметь неявно объявленные move-constructor и move-assign, но они будут =deleted, потому что нестатический элемент данных data_ только копируемый, но не перемещаемый?

Обновление. Дополнительный вопрос: для Question q; будет ли работать std::move(q)? Произойдет ли там откат к копированию? Или неявно объявленный move-ctor заставит компилятор остановиться с ошибкой? Здесь он компилируется.

Обновление 2. Что сгенерирует компилятор для неперемещаемых элементов данных, если я объявлю move-ctor Question(Question&&) =default? Это тогда откат к их копированию?


person towi    schedule 17.09.2011    source источник
comment
Вы имеете в виду, что copyOnly_ является причиной того, что Question не перемещается вместо data_, или я пропустил что-то важное?   -  person pmr    schedule 03.10.2011


Ответы (1)


Вы неправильно прочитали. Это сломает множество классов С++ 03 в таких случаях, как следующие:

Question getQuestion();
Question q(getQuestion()); // use of deleted move constructor!

Вместо этого FDIS сообщает, что конструктор перемещения будет объявлен, если и только если {нет объявленных пользователем {конструктора копирования, оператора присваивания {копирования, перемещения}, деструктора} и неявно объявленный конструктор перемещения не будет определен как удаленный}.

Относительно Обновления 2. До моего сведения было доведено, что если вы явно используете конструктор перемещения по умолчанию, он будет определен как удаленный по условию

для конструктора перемещения — нестатический член данных или прямой или виртуальный базовый класс с типом, который не имеет конструктора перемещения и не является простым копированием.

В дальнейшем конструктор перемещения будет определен как удаленный, потому что CopyOnly не является простым копированием.

 struct Question 
 {
        std::vector<int> data_;
        CopyOnly         copyOnly_;

        Question(Question&&) = default;
 };
person Johannes Schaub - litb    schedule 17.09.2011
comment
Понятно! Я проглядел последний пункт списка. Груммель. Хорошо, что я спросил. - person towi; 17.09.2011
comment
Можете ли вы также указать мне правильный абзац для моей части обновления 2? - person towi; 17.09.2011
comment
Отлично. Это целый набор вещей, которые нужно запутать. - person towi; 18.09.2011
comment
@towi, я ошибся в своем ответе на комментарий к обновлению 2. Я добавлю соответствующие части в свой ответ. - person Johannes Schaub - litb; 03.10.2011
comment
бах, SO не позволяет мне редактировать свой ответ, потому что сегодня я уже редактировал свои собственные сообщения 15 раз. надо подождать до завтра :) - person Johannes Schaub - litb; 03.10.2011
comment
@JohannesSchaub-litb: Не беспокойтесь. Обновил от вашего имени :) - person Alok Save; 03.10.2011
comment
Подобъекты только для копирования, будь то член или база, не являются проблемой для конструктора перемещения по умолчанию: coliru.stacked-crooked.com/a/aedd5ee6666a2e58 - person Deduplicator; 15.12.2015