4 Stimmen

Wird der für ein Objekt zugewiesene Speicher automatisch gelöscht, wenn in einem Konstruktor eine Ausnahme ausgelöst wird?

Angenommen, es gibt diesen Code:

class CFoo
{
public:
    CFoo()
    {
        iBar = new CBar();
    }
private:
    CBar* iBar;
};

....
CFoo* foo = new CFoo();

Wenn die obige Zeile ausgeführt wird, wird zunächst Speicher für das CFoo-Objekt zugewiesen. Aber wenn die Zeile new CBar() eine Ausnahme auslöst (wegen Speichermangels), gibt das System dann automatisch den Speicher frei, der zuvor dem CFoo-Objekt zugewiesen wurde? Ich nehme an, dass es das tun muss, kann aber keinen ausdrücklichen Hinweis darauf finden. Wenn dies nicht der Fall ist, wie kann dann der Speicher vom Programmierer freigegeben werden, da er nicht foo zugewiesen wurde?

6voto

CB Bailey Punkte 693084

Ja, der Speicher, der für die CFoo Objekt wird in diesem Fall freigegeben.

Da die Ausnahme aufgrund der fehlgeschlagenen Zuweisung die CFoo Konstruktor nicht erfolgreich abschließen kann, wird die neue-ausdruck wird garantiert, dass der für diesen Vorgang zugewiesene Speicher freigegeben wird CFoo Objekt.

Diese Garantie ist in 5.3.4 [expr.new] / 17 der ISO/IEC 14882:2003 festgelegt.

Beachten Sie, dass es immer ratsam ist, das Ergebnis einer dynamischen Zuweisung einem Smart Pointer zuzuweisen, um eine ordnungsgemäße Bereinigung zu gewährleisten. Zum Beispiel, wenn es weiteren Code in CFoo Konstruktor und das warf eine Ausnahme die CBar Objekt, das bereits zuvor im Konstruktor erfolgreich zugewiesen wurde, würde durchsickern.

3voto

Fred Larson Punkte 58721

Ja, aber bedenken Sie, was passiert, wenn es mehr als einen Mitgliederzeiger gibt:

class CFoo
{
public:
    CFoo()
    {
        iBar = new CBar();
        iBaz = new CBaz(); // Throws an exception
    }
private:
    CBar* iBar;
    CBaz* iBaz;
};

....
CFoo* foo = new CFoo();

Jetzt wird das CBar-Objekt durchgesickert. Die Verwendung von intelligenten Zeigern anstelle von nativen Zeigern würde dieses Problem beheben.

Verwenden Sie außerdem lieber Initialisierungen für Mitglieder:

class CFoo
{
public:
    CFoo() : iBar(new CBar())
    {
        // Nothing here
    }
private:
    CBar* iBar;
};

....
CFoo* foo = new CFoo();

1voto

Puppy Punkte 141483

Ja, der Speicher wird automatisch freigegeben. Betrachten Sie das folgende vereinfachte Pseudo des Operators new:

template<typename T> T* operator new() {
    void* ptr = nullptr;
    try {
        ptr = ::operator new(sizeof(T));
        return new (ptr) T();
    } catch(...) {
        ::operator delete(ptr);
        throw;
    }
}

0voto

Viren Punkte 2153

Wenn Sie sich auf den vom Compiler bereitgestellten Operator new verlassen wollen, wird der Destruktor im obigen Fall nicht aufgerufen. Der Grund: Wenn new CBar() eine Ausnahme auslöst, wird der Stack sofort abgewickelt, und das Objekt CFoo ist nicht "vollständig" konstruiert. Da es ein halb konstruiertes Objekt ist, ruft der Compiler den Destruktor für CFoo nicht auf.

Faustregel: Der Destruktor wird in C++ nur für vollständig konstruierte Objekte aufgerufen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X