Destruktor selbst aufrufen



  • Dravere schrieb:

    Shade Of Mine schrieb:

    es gibt kein placement delete.

    Ach, gibt es nicht? Ja, dann ist alles klar 😃

    Expliziter Dtor-Aufruf ist im Grunde der Counterpart zum placement-new. Wenn du irgendwo ein Objekt mit placement-new konstruierst solltest du es in den meisten (bzw. allen, mir fällt kein Gegenbeispiel ein) Fällen mit explizitem Dtor-Aufruf wieder zerstören. Den Speicher deallokierst du dann genauso wie du ihn vorher allokiert hast (z.B. als char-Array, mit free() zum malloc() usw.) Ist wie mit allen anderen Speicherbeschaffungsmaßnahmen: immer das selbe deallokations/zerstörungsverfahren anwenden wie bei der allokation/konstruktion:

    Automatische Variable -> automatischer Dtoraufruf
    new -> delete
    new[] -> delete[]
    placement-new (kein Speicher angefordert) -> expliziter Dtor-Aufruf (kein Speicher freigegeben)
    malloc -> free
    irgendeinAllocator::allocate() -> irgendeinAllocator::deallocate()

    ganz einfach eigentlich 😉
    Aus dem Grund ists auch so gefährlich, bei automatischen Variablen einen expliziten Dtoraufruf zu machen: man zerstört das Objekt anders als man es geschaffen hat. Man kanns in dem Fall eventuell wieder gutmachen, aber eben nur eventuell. Gerade bei Funktionen, in denen man das Objekt nur als Referenz oder Pointer übergeben bekommt, sollte man die Finger auf jeden Fall vom Dtor lassen - schließlich weiß man da nicht genau wie es erzeugt wurde und kann deshalb auch nicht wissen, was man mit der falschen Zerstörung alles kaputt macht (splicing etc, siehe GOTW-Artikel).



  • ghorst schrieb:

    @shade of mine code ist im standard nicht aufgeführt. dort heißt es nur in 20.4.1.1 allocator - allocator members [lib.allocator.members]
    "pointer allocate(size_type n, allocator<void>::const_pointer hint=0);
    -3- Notes: Uses ::operator new(size_t) (lib.new.delete)."

    Ich habe aber nie von operator new gesprochen sondern nur vom new operator...



  • da man ::new() nie außerhalb von new() aufrufen sollten, sind die beiden aussagen gleichwertig.



  • ghorst schrieb:

    da man ::new() nie außerhalb von new() aufrufen sollten, sind die beiden aussagen gleichwertig.

    Ich will auch nie ::new aufrufen. Habe ich noch nie gemacht.

    Kennst du den Unterschied zwischen operator new() und dem new operator?
    Sprich:
    void* p = ::operator new(sizeof(T));
    T* p = new T();

    ?



  • es gibt keinen. new() ruft entweder die standardimplementierung auf oder, wenn eine klassenspezifische gegeben ist, den operator ::new(), der sich dann um die vollständige speicherverwaltung kümmert.
    wenn ::new() nicht definiert ist, weiß ich offengestanden nicht, was passiert, wenn man den aufruft. daher ist "keinen" dahingehend mit vorbehalt zu verstehen.


  • Mod

    ghorst schrieb:

    es gibt keinen. new() ruft entweder die standardimplementierung auf oder, wenn eine klassenspezifische gegeben ist, den operator ::new(), der sich dann um die vollständige speicherverwaltung kümmert.
    wenn ::new() nicht definiert ist, weiß ich offengestanden nicht, was passiert, wenn man den aufruft. daher ist "keinen" dahingehend mit vorbehalt zu verstehen.

    Das ist wirr. Im Übrigen sind weder new() noch ::new() wohlgeformte Ausdrücke.



  • operator new(sizeof(T)) allokiert nur rohen Speicher und zwar sizeof(T) Bytes.
    new T() allokiert mindestens sizeof(T) bytes und ruft den konstruktur für ein T objekt auf.

    deshalb sind allokatoren mit dem new operator (sprich: new T()) nicht implementierbar. Man braucht rohen Speicher, den operator new liefert.



  • ja natürlich sind sie das nicht. ich hätte korrekterweise schreiben müssen: new (T); bzw. T* T::operator new(size_t);



  • Dravere schrieb:

    @Belli,
    Darum ging es aber nicht ...

    Ne, aber das hab ich als starkes Indiz dafür genommen, daß auch das Objekt, um das es geht, zerstört wird. Hältst Du diese Folgerung für falsch?


  • Administrator

    Belli schrieb:

    Ne, aber das hab ich als starkes Indiz dafür genommen, daß auch das Objekt, um das es geht, zerstört wird. Hältst Du diese Folgerung für falsch?

    Ziemlich. Ich habe es nämlich vor dem Quellcode selber hingeschrieben, dass die Destruktoren der Basisklassen aufgerufen werden. 😉

    Grüssli


Anmelden zum Antworten