Früher dachte ich, wenn in C ++ ein Konstruktor eine Ausnahme auslöst, wird der Destruktor dieser "teilweise konstruierten" Klasse nicht aufgerufen.
Aber es scheint, dass es in C ++ 11 nicht mehr stimmt
Es ist immer noch wahr. Seit C ++ 03 hat sich nichts geändert (für einen Wert von nichts ;-))
Was Sie dachten, ist immer noch wahr, aber es gibt kein teilweise konstruiertes Objekt, wenn die Ausnahme ausgelöst wird.
Der C ++ 03 TC1-Standard sagt (Hervorhebung von mir):
Bei einem Objekt, das teilweise erstellt oder teilweise zerstört wurde, werden Destruktoren für alle vollständig konstruierten Unterobjekte ausgeführt, dh für Unterobjekte, für die der Konstruktor die Ausführung abgeschlossen hat und der Destruktor noch nicht mit der Ausführung begonnen hat.
dh Jedes Objekt, das seinen Konstruktor fertiggestellt hat, wird durch Ausführen des Destruktors zerstört. Das ist eine schöne einfache Regel.
Grundsätzlich gilt in C ++ 11 dieselbe Regel: Sobald X(int)
der Objektkonstruktor die Ausführung abgeschlossen hat, ist er vollständig konstruiert, sodass er vollständig konstruiert ist und sein Destruktor zum richtigen Zeitpunkt ausgeführt wird (wenn er den Gültigkeitsbereich verlässt oder ein Die Ausnahme wird in einem späteren Stadium des Aufbaus ausgelöst.) Es ist im Wesentlichen immer noch dieselbe Regel.
Der Hauptteil des delegierenden Konstruktors läuft dem anderen Konstruktor nach und kann zusätzliche Arbeit leisten. Dies ändert jedoch nichts an der Tatsache, dass die Konstruktion des Objekts abgeschlossen ist, sodass es vollständig erstellt wird. Der delegierende Konstruktor ist analog zu einem Konstruktor einer abgeleiteten Klasse, der nach Abschluss eines Konstruktors einer Basisklasse mehr Code ausführt. In gewissem Sinne können Sie Ihr Beispiel folgendermaßen betrachten:
class X
{
public:
X(int a)
{
cout << "X::X(" << a << ")" << endl;
}
~X()
{
cout << "X destructor" << endl;
}
};
class X_delegating : X
{
public:
X_delegating() : X(10)
{
throw runtime_error("Exception thrown in X::X()");
}
};
Es ist nicht wirklich so, es gibt nur einen Typ, aber es ist insofern analog, als der X(int)
Konstruktor ausgeführt wird, dann wird zusätzlicher Code im delegierenden Konstruktor ausgeführt, und wenn dies die X
"Basisklasse" auslöst (die eigentlich keine Basisklasse ist) wird zerstört.