Явный конструктор перемещения?

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

Для конструкторов копирования он используется (запрещает неявное копирование через вызов функции, возврат и т. д.), но это не то, что обычно требуется.

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


person Kos    schedule 20.07.2011    source источник
comment
В чем разница между конструктором копирования и конструктором, который можно вызвать с одним аргументом? У меня просто была путаница с ответом DeadMG, потому что я думал, что это одно и то же. Это это именно так, как он используется, и (кроме явного) не так, как объявляется конструктор, да? Или я сошел с ума?   -  person Steve314    schedule 20.07.2011
comment
@ Steve314: Конструктор копирования с одним аргументом — это, в частности, конструктор T([const] [volatile] T&). 12,8/2. T(int) — это конструктор, который можно вызывать с одним аргументом, но он не является конструктором копирования, поскольку не копирует экземпляр T.   -  person Steve Jessop    schedule 20.07.2011
comment
@ Стив Джессоп - да, конечно. Очевидно, у меня умер мозг.   -  person Steve314    schedule 20.07.2011
comment
Спасибо за ответы! Итак, можем ли мы согласиться с тем, что нет разумной (т. е. явно полезной) причины делать это явным?   -  person Kos    schedule 20.07.2011
comment
Это также рекомендуется для конструкторов, которые можно вызывать только для нескольких аргументов в C++0x.   -  person Johannes Schaub - litb    schedule 21.07.2011
comment
@Johannes Schaub, вы имеете в виду, что в C ++ 0x есть случаи, когда ключевое слово explicit может иметь значение для таких конструкторов? Можете ли вы привести пример?   -  person Kos    schedule 22.07.2011


Ответы (5)


Конструкторы перемещения explicit могут повлиять на совместимость, например. Стандартные алгоритмы. Например, std::swap<T> требует, чтобы T был MoveConstructible. В свою очередь, MoveConstructible указывается в терминах выражения, а именно T u = rv; (где rv — это rvalue типа 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
person Luc Danton    schedule 20.07.2011

Вероятно, вам нужен неявный конструктор перемещения для большинства применений. Обычно они попадают в те же категории, что и конструкторы копирования. Явный не рекомендуется для всех конструкторов с одним аргументом, но рекомендуется для большинства. Конструкторы перемещения не входят в этот список.

person Puppy    schedule 20.07.2011

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

Конструкторы копирования и конструкторы перемещения вряд ли «удивительны» в этом смысле. Они происходят в основном там, где и ожидалось. Если они вам не нужны, я ожидаю, что они будут помечены =delete, а не явно указаны.

person Bo Persson    schedule 20.07.2011

Фактический вопрос заключается в том, как можно использовать явный конструктор перемещения? Его нельзя будет вызвать для rvalue, поэтому компилятору придется всегда выбирать конструктор копирования, если он доступен, иначе он не сможет скомпилироваться.

Изменить: вот ссылка на пример: http://www.ideone.com/nm7KM

person Gene Bushuyev    schedule 20.07.2011
comment
@Luc: это хорошо! и, вероятно, единственный способ вызвать явный конструктор перемещения. - person Gene Bushuyev; 21.07.2011
comment
+1 за хороший вопрос, Джин :) И еще больше поддержки для Люка за ответ (может быть полезно, если вы добавите его в свой пост для любых ссылок в будущем). Спасибо! - person Kos; 25.07.2011

При возврате по значению из функции неявный конструктор перемещения обычно может сделать процесс более эффективным.

person Lingxi    schedule 30.04.2012
comment
Немного не по теме, но на самом деле хороший момент - я думаю, что это причина сделать конструкторы перемещения встроенными, если это возможно. - person Kos; 01.05.2012