delete this im Konstruktor?



  • Also entweder verstehe ich dich nicht, oder du hast einen Denkfehler. Denn egal wo du delete this aufrufst, in Base oder Derived, das Objekt wird _komplett_ zerstört, also auch der komplette Speicher freigegeben. Ein weiteres Zerstören von irgendwas ist nicht mehr notwendig.


  • Mod

    objektzerstörung und speicherfreigabe sind ja zwei verschiedene dinge, die speicherfreigabe macht mir auch keine sorgen. wohl aber

    #include <iostream>
    struct A
    {
        A() { std::cout << "A ctor\n"; }
        virtual ~A() { std::cout << "A dtor\n"; }
    };
    struct B : A
    {
       B() { std::cout << "B ctor\n"; delete this; }
       ~B() { std::cout << "B dtor\n"; }
    };
    struct C : B
    {
       int* p;
       C() { p = new int; std::cout << "C ctor\n"; }
       ~C() { delete p; std::cout << "C dtor\n"; }
    };
    int main() { new C; }
    

    das halbfertige objekt wird zerstört und dann geht die konstruktion munter weiter - ups.



  • Wiedemauchsei, ein delete this im Konstruktor ist Mist! 😃



  • camper schrieb:

    das halbfertige objekt wird zerstört und dann geht die konstruktion munter weiter - ups.

    Ahh, ok. Jetzt hab ich verstanden, was dich stört. Naja, du hast ja schon ein etwas extremeres Beispiel konstruiert, was sich aus dem Code des OP nicht ablesen lässt. Dazu kann ich eigentlich auch wieder nur sagen

    Undefiniert wäre es für mich nur, wenn der Standard etwas sagt wie "ein dtor darf erst aufgerufen werden, nachdem der ctor aufgerufen wurde"

    und das muss in deinem Beispiel ja mindestens für die Initialisierungsliste vom C ctor passiert sein. Ansonsten gibt es gar keine Möglichkeit, kein undefiniertes Verhalten zu erzeugen.



  • Habe nicht die große Programmiererfahrung wie viele andere hier, also korrigiert mich bitte wenn ich jetzt falsch liege.

    Um auf das Anfangsbeispiele von Chris++ zurück zu greifen:

    class Container
    {
    public:
        Container(bool DeleteMe) {if(DeleteMe) delete this;};
        void SetzeWert(int wert) {m_wert = wert;};
        int  HoleWert()          {return m_wert;};
    
    private:
        int m_wert;
    
    };
    //.....
    int main()
    {
        Container *Eimer = NULL;
        Eimer = new Container(true);
    
        Eimer->SetzeWert(5);           //5 wird gesetzt
    
        int bla = Eimer->HoleWert();   //5 wird zurückgegebe
    
        delete Eimer;                  //unbehandelte Ausnahme
    
        bla = Eimer->HoleWert();
    
            return 0;
    }
    

    Nach meiner Meinung ist das Verhalten hier schon definiert!!!

    Es wird ein Container-Objekt erstellt und durch den Konstruktor gleich wieder zerstört. Also der physikaliche Speicher, an dem das Objekt erstellt wurde, für andere sachen in diesem Programm wieder frei gegeben.(Speicherinhalt wurde mit werten für ein Objekt des Types Container gefüllt)
    Sofort nach dem Erstellen/Zerstören des Objektes wird hier auf den Speicher zugegriffen (Funktionsaufruf). Da er jedoch noch nicht mit anderen Werten Überschrieben worden ist und zu dem Speicherbereich des Programmes gehört, meckert weder der Compiler, noch stürzt das Programm ab!!

    Jetzt kommt der Knackpunkt!!!
    Würde nach dem Erstellen/Zerstören eine andere Variable deklariert werden,
    würde der Speicher in dem das Objekt erstellt/zerstört wurde überschrieben werden.
    Erst jetzt steht "mist" im Speicher welches das Programm zum Absturz bringen würde.



  • Riker schrieb:

    Sofort nach dem Erstellen/Zerstören des Objektes wird hier auf den Speicher zugegriffen (Funktionsaufruf). Da er jedoch noch nicht mit anderen Werten Überschrieben worden ist und zu dem Speicherbereich des Programmes gehört, meckert weder der Compiler, noch stürzt das Programm ab!!

    Für dich mag der Speicher noch vorhanden und nicht überschrieben worden sein. Das weisst du, weil du vermutlich die Architektur deines Systems kennst. Aus C++ Sicht ist das aber anders. Der Speicher wurde freigegeben und ist damit nicht mehr existent, oder besser, definiert. Weder der Inhalt noch die physische Präsenz sind definiert. Und damit ist es nicht zulässig, auf diesen nun "toten" Bereich zuzugreifen. Und wie ich weiter oben schon sagte, undefiniertes Verhalten schliesst auch ein, dass unter gegeben Umständen alles fehlerfrei funktionieren kann.


Anmelden zum Antworten