c++ - copy constructor java
¿Cuál es el efecto de la palabra clave ''explícita'' en la optimización del valor de retorno(RVO)? (1)
RVO puede eludir una copia, pero las reglas del idioma requieren que una copia (o un movimiento) aún sea posible:
[C++14: 12.8/31]:
cuando se cumplen ciertos criterios, se permite que una implementación omita la construcción de copiar / mover de un objeto de clase, incluso si el constructor seleccionado para la operación copiar / mover y / o el destructor para el objeto tiene efectos secundarios. [..]
[C++14: 12.8/32]:
[..] [Nota: Esta resolución de sobrecarga de dos etapas debe realizarse independientemente de si se producirá elisión de copia. Determina el nombre del constructor que se invocará si no se realiza una elisión, y el constructor seleccionado debe estar accesible incluso si se elimina la llamada. -finalizar nota]
Ha hecho imposible la copia agregando explicit
, y un movimiento no es posible porque su constructor de copia bloquea la creación de un constructor de movimiento definido implícitamente.
En cambio, podría permitir un movimiento agregando su propio constructor de movimientos, tal vez uno predeterminado:
A(A&&) = default;
Pero esta es solo otra forma de cumplir la misma regla de lenguaje.
C ++ 17 relajará la regla de alguna forma, agregando algunas garantías de elisión de copia que no estarán sujetas a esta restricción.
El siguiente código funciona perfectamente bien (mostrando RVO):
struct A {
A (int) { cout << "A::A()/n"; } // constructor
A (const A&) { cout << "A::A(const A&)/n"; } // copy constructor
};
A foo () { return A(0); }
int main () {
A a = foo();
}
Salida:
A::A() // --> which means copy constructor is not called
Si marque el constructor de copia como explicit
:
explicit A (const A&) { ... }
Entonces el compilador comete un error:
explicit.cpp: In function ‘A foo()’:
explicit.cpp:10:22: error: no matching function for call to ‘A::A(A)’
A foo () { return A(0); }
^
explicit.cpp:5:3: note: candidate: A::A(int)
A (int) { cout << "A::A()/n"; }
^
explicit.cpp:5:3: note: no known conversion for argument 1 from ‘A’ to ‘int’
explicit.cpp: In function ‘int main()’:
explicit.cpp:14:13: error: no matching function for call to ‘A::A(A)’
A a = foo();
^
explicit.cpp:5:3: note: candidate: A::A(int)
A (int) { cout << "A::A()/n"; }
^
explicit.cpp:5:3: note: no known conversion for argument 1 from ‘A’ to ‘int’
¿Por qué está sucediendo? ¿No debería funcionar el RVO tal como es?