2012-01-28 11 views
6

Rozważmy następujący kod:Destructor nie nazywa kiedy jest wyjątek

#include <iostream> 
using namespace std; 

class Test { 
    static int count; 
    int id; 
public: 
    Test() { 
    count++; 
    id = count; 
    cout << "Constructing object number " << id << endl; 
    if(id == 4) 
     throw 4; 
    } 
    ~Test() { cout << "Destructing object number " << id << endl; } 
}; 

int Test::count = 0; 

int main() { 
    try { 
    Test array[5]; 
    } catch(int i) { 
    cout << "Caught " << i << endl; 
    } 
} 

Powyższy kod wygeneruje następujące wyniki:

Constructing object number 1 
Constructing object number 2 
Constructing object number 3 
Constructing object number 4 
Destructing object number 3 
Destructing object number 2 
Destructing object number 1 
Caught 4 

myślałem destruktory zawsze wywoływana, gdy przedmioty stają się poza zakresem , nawet gdy są zgłaszane wyjątki. Dlaczego w tym przypadku nie jest wywoływany jeden z destruktorów instancji Test?

+0

Zmodyfikowałem twoje pytanie w coś bardziej odpowiedniego dla przepełnienia stosu. Proszę postępować zgodnie z [wytycznymi dotyczącymi pytania] (http://stackoverflow.com/questions/how-to-ask), aby móc się z nimi zapoznać w przyszłości, lub pytanie może zostać wycofane/zamknięte. –

Odpowiedz

8

Tworzysz tablicę 5Test obiektów, ale wyjątek po utworzeniu 3kompletne obiektów, jest wyjątek podczas gdy w konstruktora 4 th obiektu. Konstrukcja obiektu 4 th nie jest ukończona, dopóki nie zostanie osiągnięty nawias zamykający konstruktora.

Stos odwija ​​wywołanie destruktora dla tych 3 całkowicie budowanych obiektów w odwrotnej kolejności, w jakiej zostały stworzone, ponieważ 4 th i 5 th obiekt nigdy nie zostały zbudowane destruktora dla nich nigdy nie jest wywoływana.

Reguła dla wyjątku:
Po wygenerowaniu wyjątku zostaną wywołane destruktory dla wszystkich obiektów utworzonych w tym zakresie.
Całkowicie stworzony obiekt to taki, którego konstruktor został nazwany czyściutko bez żadnych wyjątków.

+0

Ten artykuł [Guru tygodnia (# 66)] (http://www.gotw.ca/gotw/066.htm) jest szczególnie istotny w tej sytuacji. –

+0

wyłączone o jeden - są tylko 3 całkowicie skonstruowane obiekty, dlatego wywoływane są tylko 3 destruktory. –

+0

@ChrisDodd: Oh dobrze zauważony. Zapomniałem czytać ślady. –

3

Zamiast napisać oświadczenie cout po id = liczone jako wymienione poniżej: -

id = count; 
    cout << "Constructing object number " << id << endl; 
    if(id == 4) 
    throw 4; 

powinieneś napisać to po instrukcji throw. To dałoby lepsze zdjęcie tego, co się stało. W ten sposób: -

Test() { 
count++; 
id = count; 
if(id == 4) 
    throw 4; 
cout << "Constructing object number " << id << endl; 
    } 

O/P byłaby: - ​​ Konstruowanie numer obiektu 1 Budowa Numer przedmiot 2 Konstruowanie obiekt nr 3 niszczeniem liczba obiektów 3 niszczeniem numer obiekt 2 numer obiekt niszczeniem 1 Złapane 4