2012-09-24 15 views
10
#include<iostream> 
using namespace std; 

class A{ 
public: 
    static int cnt; 
    A() 
    { 
     ++cnt; 
     cout<<"constructor:"<<cnt<<endl; 
    } 
    ~A() 
    { 
     --cnt; 
     cout<<"destructor:"<<cnt<<endl; 
    } 
}; 

int A::cnt = 0; 

A f(A x){ 
    return x; 
} 
int main(){ 
    A a0; 
    A a1 = f(a0); 
    return 0; 
} 

El programa de la Salida:¿Por qué mi destructor parece ser llamado con más frecuencia que el constructor?

 
constructor:1 
destructor:0 
destructor:-1 
destructor:-2 

El constructor y el destructor no aparecen en pares?

+0

¡Bienvenido a Stack Overflow! +1 y gracias por proporcionar un programa de muestra completo. Ver http://SSCCE.ORG para saber por qué eso fue importante. –

+1

El contructor de copia invocado por 'return x;' aparentemente ya está optimizado, pero me pregunto si un optimizador suficientemente agresivo podría eliminar la invocación al invocar 'f' (' x' se pasa por valor) también. Para que efectivamente llame al destructor predeterminado una vez y luego al constructor de copia una vez. –

+1

@FrerichRaabe: esa optimización no se ajustaría al estándar, lo que permite la elisión del constructor de copias solo en ciertas circunstancias. En todas las circunstancias permitidas, la fuente o el destino de la copia eliminada es temporal. –

Respuesta

14

Necesita agregar un constructor de copia que aumente el contador.

A(const A&) 
{ 
    ++cnt; 
    cout<<"copy constructor:"<<cnt<<endl; 
} 

Si no se agrega explícitamente, el compilador genera uno que no hace nada con el contador cnt.

Esta expresión

A a1 = f(a0); 

es la creación de copias de a0, que hacen uso del constructor de copia. La cantidad exacta de copias puede variar según copy elision, pero su cnt debe ser 0 al final del programa.

Nota: En C++ 11, también se debe considerar la posibilidad de un compilador genera movimiento constructor de copia, sin embargo, una vez que se declara su propia copia constructor, el compilador ya no genera la versión de movimiento.

3

También necesita contar las llamadas al constructor de copia. En C++ 11 también hay constructores de movimientos que deben tenerse en cuenta.

5

No está siguiendo todos los constructores, solo el constructor predeterminado. El compilador generó un constructor de copia y lo usó un par de veces, teniendo en cuenta los 2 objetos que se enumeran como destruidos y no como creados.

Cuestiones relacionadas