При каких условиях я должен думать о реализации конструктора перемещения и оператора перемещения? - PullRequest
7 голосов
/ 12 декабря 2011

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

Для новых конструкторов перемещения и оператора перемещения , как правильно думать о необходимости реализации или нет?

В качестве первого этапа перехода системы из пре-C ++ 0x, могу ли я просто delete конструктор перемещения по умолчанию и оператор перемещения или я должен оставить их в покое

Ответы [ 3 ]

10 голосов
/ 12 декабря 2011

Вам не нужно беспокоиться об этом , в том смысле, что когда вы объявляете деструктор пользователем (или что-либо еще, перечисленное в 12.8 / 9), он блокирует конструктор перемещения по умолчанию от генерации,Таким образом, существует не тот же риск, что и с копиями, что значение по умолчанию неверно.

Итак, при первом проходе оставьте их в покое.В существующем коде могут быть места, в которых семантика перемещения C ++ 11 допускает перемещение, тогда как C ++ 03 диктует копию.Ваш класс будет продолжать копироваться, и если это не вызвало проблем с производительностью в C ++ 03, то я не могу сразу думать о какой-либо причине, почему это было бы в C ++ 11.Если это привело к проблемам с производительностью в C ++ 03, то у вас есть возможность исправить ошибку в вашем коде, с которой вы никогда не сталкивались раньше, но это возможность, а не обязанность; -)

ЕслиПозже вы реализуете конструкцию перемещения и присваивание, они будут перемещены, и, в частности, вы захотите сделать это, если считаете, что клиенты C ++ 11 вашего класса с меньшей вероятностью будут использовать «swaptimization», чтобы избежать копирования, с большей вероятностьюпередать ваш тип по значению и т. д., чем были клиенты C ++ 03.

При написании новых классов в C ++ 11 необходимо учитывать и реализовывать перемещение в соответствии с теми же критериями, которые вы рассматривали и реализовали swap в C ++ 03.Класс, который может быть скопирован, реализует концепцию C ++ 11 «подвижный» (подобно тому, как класс, который можно скопировать в C ++ 03, можно поменять местами с помощью реализации по умолчанию в std), потому что «подвижный» неНе говорите, в каком состоянии находится источник - в частности, он может быть неизменным.Таким образом, копия является действительной как ход, но она не обязательно эффективна, и для многих классов вы обнаружите, что в отличие от «хорошего» хода или свопа, копия может выбрасывать.

Вы можете обнаружить, что вам нужно реализовать перемещение для ваших классов в тех случаях, когда у вас есть деструктор (следовательно, нет конструктора перемещения по умолчанию), и у вас также есть член данных, который является подвижным, но не копируемым (следовательно, также нет конструктора копирования по умолчанию),Именно тогда движение становится важным как семантически, так и для производительности.

4 голосов
/ 12 декабря 2011

В C ++ 11 вам очень редко требуется указывать деструктор или семантику копирования из-за способа написания библиотеки.Предоставленные компилятором члены почти всегда работают нормально (при условии, что они реализованы правильно: MSVC заставляет вас реализовать множество семантик перемещения вручную, что очень утомительно).

В случае, если вам нужно реализовать собственный деструктор,используйте следующий подход:

  • Реализуйте конструктор перемещения и оператор присваивания, принимающий по значению (используя copy & swap: обратите внимание, что вы не можете использовать std::swap, поскольку он использует присваивание. Вы должны предоставить приватныйпоменяйся).Обратите внимание на гарантии исключений (поиск std::move_if_noexcept).
  • Если необходимо , реализуйте конструктор копирования.В противном случае удалите его.Помните, что семантика копирования по умолчанию редко имеет смысл.

Кроме того, виртуальный деструктор считается пользовательским деструктором: предоставьте или удалите семантику копирования + перемещения при объявлении виртуального деструктора.

0 голосов
/ 12 декабря 2011

Поскольку они используются в качестве оптимизации, вы должны реализовать их, если оптимизация применима к вашему классу. Если вы можете «украсть» внутренний ресурс, который ваш класс держит от временного объекта, который собирается быть уничтоженным. std :: vector является идеальным примером, когда конструктор перемещения назначает только указатели на внутренний буфер, оставляя временный объект пустым (эффективно крадя элементы).

...