2012-09-24 6 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; 
} 

Il programma di uscita volontà:Perché il mio distruttore sembra essere chiamato più spesso del costruttore?

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

Il costruttore e distruttore non compaiono in coppia?

+0

Benvenuti in Stack Overflow! +1 e grazie per aver fornito un programma di esempio completo. Vedi http://SSCCE.ORG perché è importante. –

+1

Il contructor di copia invocato da 'return x;' è apparentemente ottimizzato, ma mi chiedo se un ottimizzatore sufficientemente aggressivo possa rimuovere l'invocazione quando chiama 'f' (' x' viene passato per valore). In modo efficace, si chiama il distruttore predefinito una volta e quindi il costruttore copia una volta. –

+1

@FrerichRaabe: quell'ottimizzazione non sarebbe conforme allo standard, il che consente l'elisione del costruttore di copie solo in determinate circostanze. In tutte le circostanze consentite, la fonte o la destinazione della copia elisa è temporanea. –

risposta

14

È necessario aggiungere un costruttore di copia che aumenti il ​​contatore.

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

Se non si aggiunge esplicitamente, il compilatore genera uno che non fa nulla con il contatore cnt.

Questa espressione

A a1 = f(a0); 

sta creando copie di a0, che fanno uso del costruttore di copia. Il numero esatto di copie può variare a seconda di copy elision, ma il tuo cnt dovrebbe essere 0 alla fine del programma.

Nota: In C++ 11, si dovrebbe anche prendere in considerazione la possibilità di un compilatore generato mossa costruttore di copia, tuttavia, una volta si dichiara il proprio costruttore di copia, il compilatore non genera più la versione mossa.

3

È necessario contare anche le chiamate del costruttore di copia. In C++ 11 ci sono anche costruttori di movimento che devono essere presi in considerazione.

5

Non si sta rilevando il tutti i costruttori, solo il costruttore predefinito. Il compilatore ha generato un costruttore di copie e lo ha usato un paio di volte, tenendo conto dei 2 oggetti che sono elencati come distrutti e non come creati.

Problemi correlati