2011-07-20 20 views
22

El explicit palabra clave se recomienda para todos los más constructores, que se pueden llamar con un argumento, a excepción de constructores de copia.¿Constructor de movimiento explícito?

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

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

+0

¿Cuál es la diferencia entre un "constructor de copia" y un "constructor que se puede invocar con un argumento"? Solo tuve una confusión de momentos con la respuesta de DeadMGs porque pensé que eran lo mismo. Este * es * solo la forma en que se usa, y (aparte de "explícito") no es como se declara el constructor, ¿sí? ¿O me he vuelto loco? – Steve314

+3

@ Steve314: Un constructor de copia de argumento único es específicamente un constructor 'T ([const] [volátil] T &)'. 12.8/2. 'T (int)' es un constructor que puede invocarse con un argumento, pero no es un constructor de copia porque no "copia" una instancia de 'T'. –

+0

@Steve Jessop - sí, por supuesto. Obviamente he muerto cerebralmente. – Steve314

Respuesta

19

Un explicit constructores de movimiento pueden 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, concretamente T u = rv; (donde rv es un valor de referencia del tipo T).

Si no hay ni 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, usando T u(rv);).

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

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

  • la Deleter de unique_ptr<T, D>
  • envoltorios de llamadas, por ejemplo, se utiliza en bind (todos los tipos cariados que se transmiten se refiere)
  • thread, async, call_once (todo se especifica en términos de envolturas llamadas)
  • sort, stable_sort, nth_element, sort_heap
5

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

5

se recomienda La palabra clave explicit para (un solo argumento) conversión de constructores, para evitar sorpresas en lugares inesperados.

Los constructores de copias y los constructores de movimientos no son "sorprendentes" en ese sentido. Suceden en gran parte donde se espera. Si no los quiere, esperaría que se marquen =delete en lugar de hacerlo explícito.

2

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 debería seleccionar siempre un constructor de copia, si está disponible, o no compilar.

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

+0

[Uso de la inicialización directa] (http://www.ideone.com/W2BT3). –

+0

@Luc: ¡es bueno! y probablemente la única forma en que se puede invocar el constructor de movimientos explícitos. –

+0

+1 para una buena pregunta, Gene :) Y más accesorios para Luc para la respuesta (podría ser útil si la agregases a tu publicación para futuras referencias). ¡Gracias! – Kos

0

Al regresar por el valor de una función, un movimiento constructor implícito por lo general puede hacer el proceso más eficiente.

+0

Un poco fuera de tema, pero es un buen punto, de hecho, creo que es una razón para hacer constructores de movimiento en línea si es posible. – Kos

Cuestiones relacionadas