2010-04-13 20 views
17

Mi scuso se la domanda suona stupida, stavo seguendo gli esperti in SO e provando alcuni esempi me stesso, e questo è uno di loro. Ho provato l'opzione di ricerca ma non ho trovato una risposta per questo tipo.Perché il distruttore della classe ha chiamato due volte?

class A 
{ 
    public: 
     A(){cout<<"A Contruction"<<endl;} 
     ~A(){cout<<"A destruction"<<endl;} 
}; 

int main() 
{ 
    vector<A> t; 
    t.push_back(A()); // After this line, when the scope of the object is lost. 
} 

Perché il distruttore della classe ha chiamato due volte?

+0

Non credo che SO supporti il ​​tag ''. Tuttavia, forse una richiesta di funzionalità su meta? Mi sembra che Jeff lo adorerà! :-) –

+0

@pst: Grazie, stavo facendo la modifica e prima che potessi salvare era fatta. – dicaprio

+5

Mi chiedo solo, perché questo wiki della comunità? – jasonline

risposta

39

Per aggiungere l'elemento, viene richiamato un costruttore di copia su un oggetto temporaneo. Dopo lo push_back() l'oggetto temporaneo viene distrutto - questa è la prima chiamata del distruttore. Quindi l'istanza vector esce dall'ambito e distrugge tutti gli elementi archiviati, ovvero la seconda chiamata al distruttore.

+0

@ sharptooth & @Andreas: Grazie. Ho appena provato dopo aver visto la tua risposta, ho definito un costruttore di copia A (ConstA &) e sì viene chiamato. – dicaprio

+3

@dicaprio: Certo, fino a quando non hai definito il tuo costruttore di copie il compilatore ha utilizzato il proprio costruttore di copie generato automaticamente. – sharptooth

4

Il distruttore viene chiamato una volta quando il temporaneo inviato a push_back viene distrutto e una volta quando l'elemento in t viene distrutto.

19

Questo ti mostrerà ciò che è happening:

struct A { 
    A() { cout << "contruction\n"; } 
    A(A const& other) { cout << "copy construction\n"; } 
    ~A() { cout << "destruction\n"; } 
}; 

int main() { 
    vector<A> t; 
    t.push_back(A()); 
} 
+0

! Roger: Ho provato la stessa cosa prima di pubblicare questo, ho capito, grazie !! – dicaprio

0

Molto probabilmente, si sta creato la copia del vostro oggetto. Per questo motivo, il distruttore per l'oggetto copiato e per l'oggetto originale effettua il conteggio delle chiamate = 2.

Esempio: anche se si passa il riferimento oggetto ad una classe, questo invocherà internamente il costruttore di copia. Per evitare questo, il bambino di classe (a cui si sta passando il genitore di riferimento, deve essere il più;

Parent *const &p parentRef; //Child.h 

Poi, l'oggetto padre verrà passato come;

// Parent.cpp 
Parent *parentObj = this; 
Child *childObj = Child(parentObj); 

Inoltre, è possibile eseguire il debug del invocazione costruttore di copia, sovrascrivendo;

Parent(const Parent& object){ 
     cout <<"copy called.." << endl; 
} 
... 

Maggiori informazioni @[email protected]

1

Esistono due chiamate al distruttore in quanto vi sono due oggetti: l'argomento su push_back e l'elemento appena aggiunto all'interno di vectort.

STL containers copie in negozio. Nel tuo esempio l'elemento aggiunto allo vector da push_back è una copia costruita dall'argomento passato a push_back. L'argomento è A(), che è un oggetto temporaneo, vedere here (variant 4).

Espansione della risposta un po ', anche se non è stato chiesto esplicitamente: Potrebbe essere utile sapere quando il temporaneo viene distrutto. Lo standard (N4140) sais abbastanza chiaramente in 12.2 p3:

... oggetti temporanei vengono distrutti come ultimo passo nella valutazione del piena espressione (1.9) che (lessicalmente) contiene il punto in cui sono stati creati ...

Nota a margine: se si utilizza emplace_back c'è un solo oggetto. Il nuovo elemento nel contenitore è costruito direttamente dagli argomenti di emplace_back. Molti container STL hanno appreso una variante di emplace in C++ 11.

Problemi correlati