c++ - ¿Por qué no se me proporciona un constructor de copia predeterminado de un objeto volátil?
copy-constructor volatile (2)
Este codigo
class X {
int member;
};
volatile X a;
X b = a;
Falla con el error:
prog.cpp:6:7: error: no matching function for call to ‘X::X(volatile X&)’
prog.cpp:6:7: note: candidates are:
prog.cpp:1:7: note: X::X()
prog.cpp:1:7: note: candidate expects 0 arguments, 1 provided
prog.cpp:1:7: note: X::X(const X&)
prog.cpp:1:7: note: no known conversion for argument 1 from ‘volatile X’ to ‘const X&’
¿Hay alguna forma en que pueda hacer que el compilador genere un constructor de copia volátil para mí?
El problema clave es que no proporciona un constructor de asignación . En consecuencia, el compilador genera uno por defecto para ti:
X& X::operator =(const X& x){
this.member = x.member;
return *this;
}
El constructor de asignación predeterminado acepta el tipo de argumento como const X y en el que const es un const de bajo nivel y no se ignorará como const .
Su código X b = a
significa llamar al constructor predeterminado. Pero su argumento a
tiene a
tipo volátil X (se puede convertir a volátil X & y volátil const X & ) no se puede convertir a const X & implícitamente.
Por lo que debe definir su propio constructor de asignación como
X& X::operator =(volatile const X&);
EDITAR
Me sorprende que tantos chicos piensen que se llama al constructor de copia (o llamada inicialización de copia ) cuando se usa el operador de asignación . Tal vez llamarlo operador de asignación no es común. Sin embargo, lo que me importa es qué método se llama.
Puede consultar esta publicación: Copiar constructores, operadores de asignación y asignación de excepción segura y Operador de asignación predeterminado
EDITAR
Cometí un error anteriormente. X b = a
es solo un proceso de inicialización. No hay asignación involucrada. Disculparme por mi mensaje de error.
La respuesta corta es: porque la norma dice que no lo harás.
El estándar C ++ 12.8 / 9 (borrador N3242) dice:
El constructor de copia declarado implícitamente para una clase X tendrá la forma
- X :: X (const X &)
Si
- cada clase base directa o virtual B de X tiene un constructor de copia cuyo primer parámetro es de tipo const B & o const volatile B &, y
- para todos los miembros de datos no estáticos de X que son de un tipo de clase M (o conjunto de ellos), cada tipo de clase tiene un constructor de copia cuyo primer parámetro es de tipo const M & o const volatile M &. [Nota: 119]
De lo contrario, el constructor de copia declarado implícitamente tendrá la forma
- X :: X (X &)
La nota 119 dice:
Esto implica que el parámetro de referencia del constructor de copia declarado implícitamente no puede vincularse a un lvalor volátil ; ver C.1.9 .
En C.1.9 encontrarás:
El constructor de copia declarada implícitamente y el operador de asignación de copia declarada implícitamente no pueden hacer una copia de un lvalor volátil. Por ejemplo, lo siguiente es válido en ISO C:
struct X { int i; };
volatile struct X x1 = {0};
struct X x2(x1); // invalid C++
struct X x3;
x3 = x1; // also invalid C++
Justificación: varias alternativas fueron debatidas en detalle. Cambiar el parámetro a volatile const X & complicaría enormemente la generación de código eficiente para objetos de clase. La discusión de proporcionar dos firmas alternativas para estas operaciones definidas de manera implícita generó preocupaciones sin respuesta sobre la creación de ambigüedades y la complicación de las reglas que especifican la formación de estos operadores de acuerdo con las bases y los miembros.