Ist 'this->~T();' möglich?



  • Doch, es kann sinnvoll sein:

    T& operator=(const T& rhs)
    {
    this->~T(); // altes Objekt löschen
    new (this) T(rhs); // copy-ctor aufrufen
    return *this;
    }
    

    Vorteil ist, dass die Zuweisung genauso wie Konstruktion funktioniert, wobei sich allerdings arge Probleme ergeben, wenn new fehlschlägt: Dann hat man nämlich ein uninitialisiertes Objekt am Hals, das man nicht mehr los wird... Also im Endeffekt doch nicht so sinnvoll 😉
    Ein anderer Grund ist, dass man den Speicher selber verwalten will, z.B. wie std::vector:

    // Platz für 5 Objekte reservieren, aber vorerst nur 2 Objekte speichern
    T* data = (T*)malloc(sizeof(T) * 5);
    new (data) T;
    new (data + 1) T;
    
    void push_back(const T& obj)
    {
    // Neues Objekt im Array speichern
    new (data + 2) T(obj);
    }
    


  • Der Tipp, ich solle "delete this" benutzen funktioniert nicht (oder es liegt an mir). Ich habe folgende Test-Klasse geschrieben, um mal auszuprobieren:

    class Test {
    public:
    	~Test() { cout<<"wird aufgerufen\n"; }
    	void destructor() { delete this; }
    };
    

    Bekomme ne Debug Assertion Failed-Meldung.

    Wie war das mit delete this gemeint?



  • Hallo,
    den Beitrag von Tag bitte ignorieren. Was er da vorstellt ist ein absolutes Anti-Idiom und sollte niemals in einem ordentlichen C++ Programm auftauchen
    (die vielen Probleme dieses Anti-Idiom werden z.B. in Herb Sutters "Exceptional C++" diskutiert).

    Die "richtige" Variante des op= wäre:

    T& operator=(const T& other)
    {
        T temp(other);
        Swap(temp);
        return *this;
    }
    

    Das drückt Copy-Assignment auch mit Hilfe von Copy-Construction aus, hat aber keines der Probleme der Anti-Idiom-Variante (kein Slicing, keine Exception-Safety-Probleme usw.).

    so das man gezwungen ist (hier in einer besonderen Situation bei mir), den Destruktor explizit aufzurufen:

    Es gibt nur *eine* Situation in der man gezwungen ist einen Dtor explizit aufzurufen: nämlich dann, wenn man ein Objekt per placement new angelegt hat. Eine Sache, die äußerst selten vorkommt.

    Sollte this->~T(); also das Objekt loeschen und den Speicher im Heap genauso freigeben wie 'delete this'?

    Nein. Ersteres ruft nur den Dtor des Objekts auf. Letzteres ruft erst den Dtor des Objekt und dann die zur new passenden operator delete-Funktion auf.



  • Hallo,
    delete this ist nur ok, wenn alle hier genannten Bedingungen erfüllt sind.

    Mich dünkt der ein oder andere hier hat die korrekte Verwendung von C++ bisher nicht verstanden.



  • Ich hab mal ne Klasse geschrieben deren abgeleitete Klassen nur aufm Heap erstellt werden können und jederzeit mit delete this zerstört werden können, falls der Threadersteller sowas machen wollte (er hat ja nicht gesagt, was er wollte).

    Hier die Klasse:

    class Base
    {
    protected:
        virtual inline void del(){}
    private:
        inline ~Base(){}
    public:
        Base(){}
        virtual void destroy(){del(); delete this;}
        friend void* operator new(size_t);
        friend void  operator delete(void*, size_t);
    };
    

    Ich hab noch festgestellt, dass man den Destruktor der abgeleiteten Klassen überhaupt nicht erwähnen sollte, sondern alles in die Funktion del() packen sollte.

    mfg Glamdring



  • Hallo,
    du solltest deinen Dtor dringend virtual machen.



  • Ich habe doch geschrieben, dass der angesprochene operator= nicht gut ist... 🙄

    (die vielen Probleme dieses Anti-Idiom werden z.B. in Herb Sutters "Exceptional C++" diskutiert).

    Rate mal, woher dieses "doch nicht so sinnvoll"e Anti-Beispiel stammt 😉



  • tag schrieb:

    Ich habe doch geschrieben, dass der angesprochene operator= nicht gut ist... 🙄

    Mir war dein Hinweis ehrlich gesagt zu "kleingedruckt" 🙂
    Deshalb wollte ich das noch mal etwas expliziter machen.



  • HumeSikkins schrieb:

    Mir war dein Hinweis ehrlich gesagt zu "kleingedruckt" 🙂

    Na gut, das sehe ich ein 🙂



  • @Hume: Nee, dann könnten abgeleitete Klassen ihrer Destruktor auch public machen und müssten nicht unbedingt auf dem Heap erzeugt werden. Die Funktion del ist in dem Fall der Pseudo-Destruktor, wenn also ein Pointer drinn ist schreibst du:

    virtual void Derrived::del()
    {
        delete Pointer;
    }
    

    Dadurch ist kein Speicherloch entstanden


Anmelden zum Antworten