2011-08-25 17 views
8

En la programación genérica libro y el TEL (edición china), que dice:constructor o constructor de copia?

X x = X() llamará al constructor de copia.

Parece un poco raro para mí. Y escribo un programa de prueba de este tipo

#include <iostream> 

class Test { 

public: 

    Test() { 
     std::cout << "This is ctor\n"; 
    } 

    Test(const Test&) { 
     std::cout << "This is copy-ctor\n"; 
    } 

}; 

int main(int argc, char** argv) 
{ 

    Test t = Test(); 
    return 0; 
} 

La salida es "Se trata de Héctor". ok, ahora estoy confundido, ¿qué es correcto?

Respuesta

9

Nominalmente sí, se construye por defecto un temporal, y luego se invoca el constructor de copia para copiarlo en su objeto t.

Sin embargo, en la práctica, la copia puede ser optimizado a cabo — a pesar de que tiene efectos secundarios (la salida de la consola):

[n3290: 8.5/16]: [..] En ciertos casos, una implementación es Permitida para eliminar la copia inherente en esta inicialización directa construyendo el resultado intermedio directamente en el objeto que se inicializa; ver 12.2, 12.8.

y (en conjunción con el ejemplo dado en la misma cláusula):

[n3290: 12.2/2]: [..] Una implementación puede utilizar un temporal en que para la construcción de X (2) antes de pasarlo a f() usando X copia constructor; alternativamente, X(2) se puede construir en el espacio utilizado para contener el argumento. [..]

Pero el constructor de copia qué todavía tienen que existir, a pesar de que no podría ser invocada.

De todos modos, si se compila con optimizaciones apagado (o, con GCC, posiblemente -fno-elide-constructors), verá:

This is ctor 
This is copy-ctor 
+2

En gcc, puede que tenga que usar '-fno-elide-constructors', ya que incluso' -O0' no evita la elisión, creo. –

+0

@Kerrek: ¡Gracias! –

+0

La copia puede elide incluso cuando no es * trivial *, la copia se elimina al construir el temporal en lugar de la variable local. La complejidad del objeto o la copia es irrelevante para esa optimización. –

4

En teoría, X x = X() llamará al constructor por defecto para crear un objeto temporal, y cópielo en x usando el constructor de copia.

En la práctica, los compiladores pueden omitir la parte de construcción de copia y construcción predeterminada x directamente (que, como David señala en su comentario, todavía requiere que el constructor de copia sea sintácticamente accesible). La mayoría de los compiladores lo hacen al menos cuando las optimizaciones están habilitadas.

+4

Es importante tener en cuenta que el constructor de copias debe estar disponible, incluso si se elimina la copia. Es decir, si no es accesible, el compilador rechazará la línea con un error. –

+0

@David: tienes razón. Lo he incorporado a mi respuesta. Gracias por mencionar esto. – sbi

2

Este es un caso en el que un formulario de Return Value Optimisation(RVO) (también conocido como Copy Elision) puede ayudar mucho en la optimización. La página wikipedia vinculada tiene una muy buena explicación de lo que está sucediendo.

+3

No creo que sea estrictamente correcto. No hay una llamada de función aquí que devuelva una 'X' (recuerde que los constructores no tienen valores devueltos). Esto es copia elisión, que es un concepto relacionado, pero distinto. –

+0

Estoy de acuerdo. Esto no es estrictamente RVO (aunque está relacionado). –

+0

@Tomak: Esto no es completamente incorrecto también. Esta es una variante de * ese tipo * de optimización. +1 para contrarrestar el downvote. –

Cuestiones relacionadas