c++ c++11 explicit-constructor move-constructor

c++ - ¿Constructor de movimiento explícito?



c++11 explicit-constructor (5)

La palabra clave explicit se recomienda para la mayoría de los constructores, a los que se puede llamar con un solo argumento , excepto para los constructores de copia.

Para los constructores de copias , tiene un uso (para prohibir la copia implícita a través de la llamada de función, devolución, etc.), pero no es lo que se suele desear.

¿Qué pasa con los constructores de movimiento ? ¿Hay algún caso de uso razonable para hacerlos explícitos? ¿Cuál es la buena práctica aquí?


¿La pregunta real es cómo se podría usar el constructor de movimiento explícito? No se podría invocar en rvalues, por lo que el compilador tendría que seleccionar siempre un constructor de copia, si está disponible, o no compilar.

Edición: aquí está el enlace al ejemplo: http://www.ideone.com/nm7KM


Cuando se devuelve por valor desde una función, un constructor de movimiento implícito generalmente puede hacer que el proceso sea más eficiente.


La palabra clave explicit se recomienda para (argumento único) convertir constructores, para evitar conversiones sorprendentes en lugares inesperados.

Copiar constructores y mover constructores no son "sorprendentes" en ese sentido. Ocurren en gran parte donde se espera. Si no los quiere, esperaría que estuvieran marcados =delete lugar de hacerlos explícitos.


Probablemente desee un constructor de movimiento implícito para la mayoría de los usos. En general, caen en las mismas categorías que los constructores de copia. Explícito no se recomienda para todos los constructores de un solo argumento, pero se recomienda para la mayoría. Los constructores de movimientos no están en esa lista.


Un constructor de movimiento explicit puede afectar la compatibilidad con, por ejemplo, algoritmos estándar. Por ejemplo, std::swap<T> requiere que T sea ​​MoveConstructible. A su vez, MoveConstructible se especifica en términos de una expresión, a saber, T u = rv; (donde rv es un valor de tipo T ).

Si no hay un constructor de copia no explícito ni un constructor de movimiento no explícito para un tipo dado, entonces T u = rv; no es válido y ese tipo no se puede usar con std::swap . (En este caso particular, sin embargo, es posible especializar std::swap para proporcionar la funcionalidad deseada, por ejemplo, utilizando T u(rv); ).

En pocas palabras, un constructor explicit movimiento o copia desafía las expectativas y no se puede utilizar también con código genérico.

Algunas otras partes de la biblioteca estándar que ponen un requisito MoveConstructible:

  • el eliminador de unique_ptr<T, D>
  • llamadas envolturas, utilizadas en, por ejemplo, bind (todos los tipos cariados que se pasan están relacionados)
  • thread , async , call_once (todo especificado en términos de envoltorios de llamadas)
  • sort , stable_sort , nth_element , sort_heap