Безопасно ли полагаться на неявно объявленный конструктор перемещения?

Вот где я получил большую часть этой информации: http://en.cppreference.com/w/cpp/language/move_constructor

По-видимому, это условия для неявно сгенерированного конструктора перемещения:

  • нет никаких заявленных пользователем конструкторов копирования
  • нет заявленных пользователем операторов копирования
  • нет пользовательских операторов перемещения
  • нет деструкторов, объявленных пользователем
  • неявно объявленный конструктор перемещения не определен как удаленный
  • если присутствует объявленный пользователем конструктор перемещения, все еще возможно принудительно генерировать неявно объявленный конструктор перемещения с ключевым словом default

Мои вопросы:

  1. Безопасно ли полагаться на неявный конструктор автоматического перемещения?
  2. Как проверить, действительно ли это работает вместо конструктора копирования по умолчанию?
  3. Наконец, и самое главное, это хорошая идея и почему? Или всегда лучше определить свое?

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

2 ответа

Решение

Вот ответы на ваши вопросы:

  1. Что вы имеете в виду под "безопасным"? Когда применяются правила, то есть подобъекты являются подвижными, и вы ничего не сделали, чтобы помешать генерации конструктора перемещения, он будет создан и использован при его наличии. Однако обратите внимание, что легко иметь неподвижный подобъект, который будет несколько незаметно препятствовать созданию конструктора перемещения.
  2. Чтобы увидеть, получил ли ваш класс конструктор перемещения, просто временно добавьте пустую базовую запись в журнал, когда используются копия и конструкторы перемещения, и принудительно переместите / скопируйте объект: он запишет соответствующий используемый конструктор.
  3. Нет кода, как правило, лучше, чем любой код.

1, Безопасно ли полагаться на неявный конструктор автоматического перемещения?

Ничто не является безопасным, на которое можно положиться без тестирования (неявного или явного).

2, Как проверить, действительно ли это работает вместо конструктора копирования по умолчанию?

Тестирование. Смотрите пример теста ниже.

3, Наконец, и самое главное, это хорошая идея и почему? Или всегда лучше определить свое?

Есть определенные (и растущие) преимущества, которые делают ваши специальные члены тривиальными. Тривиальный специальный член - тот, который определен / предоставлен компилятором. Вы можете объявить тривиальный член с = default, На самом деле это последнее предложение является преувеличением. Если вы объявите специального члена с = defaultэто точно не будет тривиальным. Это зависит от ваших членов и баз. Но если вы определите специальный член явно (как в C++98/03), то наверняка он не будет тривиальным. Если у вас есть выбор между предоставленным пользователем и тривиальным, предпочтите тривиальный.

Кроме того, вам не нужно проверять, если ваш тип X имеет конструктор перемещения. Вы должны проверить это, если вы двигаетесь XТо, что у него есть правильное исключение безопасности и правильное исполнение. Если X::X(const X&) выполняет эту задачу, пусть будет так. В таком случае X::X(X&&) не обязательно.

Если вы ожидаете, что ваш тип X будет иметь конструктор метания копии, и гораздо быстрее noexcept Конструктор перемещения, вот действительно хороший тест, чтобы подтвердить, что это так:

static_assert(std::is_nothrow_move_constructible<X>::value,
                                "X should move construct without an exception");

Поместите этот тест прямо в ваш источник / заголовок. Теперь, независимо от того, неявно ли вы, явно или явно объявляете или определяете свои специальные члены, у вас есть конкретный тест во время компиляции, который практически не требует затрат. static_assert генерирует нулевой код и потребляет незначительное количество времени компиляции.

Другие вопросы по тегам