c++ - ¿Puede un constructor de movimiento estar implícito?
visual-c++ c++11 (2)
Considera la siguiente clase:
class A
{
public:
std::string field_a;
std::string field_b;
}
Ahora considere la siguiente construcción de copia:
A a1(a2);
La construcción de copias copiará adecuadamente A
pesar de la falta de un constructor de copia explícito porque los constructores de copia para std::string
serán llamados por el constructor de copia implícita generado por el compilador.
Lo que deseo saber es, ¿es lo mismo para la construcción de movimientos?
EDITAR : las pruebas aquí muestran que:
A a2(std::move(a1));
En realidad resultará en una construcción de copia, a menos que el constructor de movimiento específico:
A( A && other ) : a(std::move(other.a)) {}
Se define.
EDITAR EDITAR Señalé a Stephan T Lavavej y le pregunté por qué VC 2012 no parece seguir lo que dice el borrador 12.8 sobre la generación implícita de constructores de movimientos. Él tuvo la amabilidad de explicar:
Es más una "característica aún no implementada" que un error. VC actualmente implementa lo que yo denomino referencias rvalue v2.0, donde los ctors / asignaciones de movimiento nunca se generan implícitamente y nunca afectan la generación implícita de copiadores / asignadores. C ++ 11 especifica las referencias rvalue v3.0, que son las reglas que estás viendo.
El compilador sintetiza un constructor de movimiento si puede y si no hay un constructor de copia definido por el usuario. La restricción de que no se sintetiza ningún constructor de movimiento si hay un constructor de copia está destinada a evitar la ruptura del código existente. Por supuesto, todos los miembros deben ser móviles. Las reglas exactas son un poco más complicadas.
Sí, del borrador de C ++ 11, 12.8:
Si la definición de una clase X no declara explícitamente un constructor de movimiento, se declarará implícitamente como predeterminado si y solo si
- X no tiene un constructor de copia declarado por el usuario,
- X no tiene un operador de asignación de copia declarado por el usuario,
- X no tiene un operador de asignación de movimiento declarado por el usuario,
- X no tiene un destructor declarado por el usuario, y
- el constructor de movimiento no se definiría implícitamente como eliminado.
La última condición se especifica con más detalle más adelante:
Un constructor de copia / movimiento implícitamente declarado es un miembro público en línea de su clase. Un constructor de copia / movimiento predeterminado para una clase X se define como eliminado (8.4.3) si X tiene:
- un miembro de variante con un constructor correspondiente no trivial y X es una clase similar a unión,
- un miembro de datos no estáticos del tipo de clase M (o matriz del mismo) que no se puede copiar / mover porque la resolución de sobrecarga (13.3), aplicada al constructor correspondiente de M, resulta en una ambigüedad o una función que se elimina o inaccesible del predeterminado constructor,
- una clase base B directa o virtual que no se puede copiar / mover porque la resolución de sobrecarga (13.3), aplicada al constructor correspondiente de B, da como resultado una ambigüedad o una función que se elimina o no se puede acceder desde el constructor predeterminado.
- cualquier clase base directa o virtual o miembro de datos no estáticos de un tipo con un destructor que se elimina o inaccesible del constructor predeterminado,
- para el constructor de copias, un miembro de datos no estáticos del tipo de referencia rvalue, o
- para el constructor de movimiento, un miembro de datos no estático o una clase base directa o virtual con un tipo que no tiene un constructor de movimiento y no se puede copiar trivialmente.
Hablando claro, el constructor de movimientos se declarará implícitamente si:
- La clase no tiene ninguna de las otras funciones especiales miembro declaradas por el usuario.
- El constructor de movimientos se puede implementar con sensatez moviendo todos sus miembros y bases.
Su clase obviamente cumple con estas condiciones.