Явный конструктор перемещения?
explicit
Ключевое слово рекомендуется для всех большинства конструкторов, которые можно вызывать с одним аргументом, за исключением конструкторов копирования.
Для конструкторов копирования он имеет применение (запретить неявное копирование с помощью вызова функции, возврата и т. Д.), Но это не то, что обычно требуется.
А как насчет конструкторов перемещения? Есть ли разумные варианты использования, чтобы сделать их явными? Какая хорошая практика здесь?
5 ответов
explicit
конструкторы перемещения могут влиять на совместимость, например, со стандартными алгоритмами. Например, std::swap<T>
требует, чтобы T
быть MoveConstructible. В свою очередь, MoveConstructible указывается в терминах выражения, а именно T u = rv;
(где rv
это значение типа T
).
Если для данного типа нет ни явного конструктора копирования, ни неявного конструктора перемещения T u = rv;
является недействительным, и этот тип не может быть использован с std::swap
, (В этом конкретном случае, однако, можно специализировать std::swap
обеспечить желаемую функциональность, например, с помощью T u(rv);
).
Проще говоря, explicit
Конструктор перемещения или копирования не соответствует ожиданиям и не может использоваться вместе с общим кодом.
Некоторые другие части стандартной библиотеки, которые предъявляют требование MoveConstructible:
- удалитель
unique_ptr<T, D>
- обертки вызовов, используемые, например, в
bind
(все распущенные типы, которые передаются, касаются) thread
,async
,call_once
(все указано в терминах оберток вызовов)sort
,stable_sort
,nth_element
,sort_heap
Вы, вероятно, хотите использовать неявный конструктор перемещения для большинства применений. Они обычно попадают в те же категории, что и конструкторы копирования. Явное не рекомендуется для всех конструкторов с одним аргументом, но рекомендуется для большинства. Конструкторы перемещения отсутствуют в этом списке.
explicit
ключевое слово рекомендуется для (одного аргумента) преобразования конструкторов, чтобы избежать неожиданных преобразований в неожиданных местах.
Копирующие конструкторы и конструкторы перемещения вряд ли "удивительны" в этом смысле. Они происходят в основном там, где ожидали. Если вы не хотите их, я ожидаю, что они будут отмечены =delete
вместо того, чтобы сделать явным.
Вопрос в том, как можно использовать явный конструктор перемещения? Он не сможет быть вызван для значений rvalue, поэтому компилятор должен всегда выбирать конструктор копирования, если он доступен, или не компилироваться.
Изменить: вот ссылка на пример: http://www.ideone.com/nm7KM
При возврате по значению из функции неявный конструктор перемещения обычно может сделать процесс более эффективным.