'delete this' oder 'pools und vererbung'



  • Stilfrage: Ist delete this; legitim?

    OK: in dieser Form braucht man es selten. Aber (wieder mal typisch für mich) bei mir sind die Verhältnisse nicht so einfach. Ich habe nämlich einen Allocator - std::allocator-interface- (mit einer vom DEBUG-Präprozessor-Makro abhängigen Policy), der zum Freigeben der Daten eben den exakten Datentyp und die Anzahl der Elemente braucht (also effektiv sizeof(x)).

    Normalerweise gar kein Problem, mit templates und der ganzen Sch****... Aber ich möchte nun einen Pointer vom Typ base * löschen. base ist eine abstrakte Basisklasse. Jetzt kann ich ja nicht einfach alloc_base.deallocate(p, 1); machen. Er würde annehmen, der Pointer wäre vom Typ base und gibt nur sizeof(base) Bytes frei. Argh. Aber nicht verzweifeln, nichts ist unmöglich: Momentan hab ich einfach in base:

    class base {
    public:
    ...
    virtual void self_destruct() = 0;
    };
    

    Und dann in der abgeleiteten Klasse:

    class deriv : public base {
    ...
    void self_destruct() { alloc_deriv.destroy(this); alloc_deriv.deallocate(this, 1); }
    };
    

    Jippie! Jetzt gehts. Einziges Problem: Ich hab das Gefühl, dass das eventuell designtechnisch nich so hübsch ist. Deutet das auf einen Design-Fehler meinerseits hin? Wenn ja, was sollte ich anders machen? Oder ist delete this; in diesem Sinne eben doch akzeptabel?

    Danke im Vorraus,
    MrN

    PS:
    delete this; selber ist eigentlich ja meistens non-sense. Das liegt daran, dass 1. die meisten malloc/free-Funktionen die Größe des Blockes in dessen Header speichern (jaja, der K&R is halt doch nich obsolet 🤡)
    2. delete p; falls der destruktor virtuell ist die Daten ansonsten auch noch aus der vtable lesen kann.

    PPS: Ich weiß, dass der Standard keine vtables kennt.



  • delete this ist legitim. und nicht nur das:

    myclass::foo()
    {
      do_sth();
      delet this;
      return irgendwas;
    }
    

    liefert sogar noch den rückgabe wert.
    Das hat mir vor ein paar wochen mal bei ner verketteten liste geholfen, die sich dadurch selbst verwalten konnte*danochmalweiterbastelnmuss*



  • THE_FreaK schrieb:

    ... liefert sogar noch den rückgabe wert.

    DAS klingt gefährlich. IIRC ist NICHT garantiert, dass man nach dem delete auf das Objekt zugreifen darf. anders ausgedrückt: man darf this nichtmehr dereferenzieren. oder tust du das gar nicht?

    auf jeden fall: ich verwend jetzt erstmal mein self_destruct() - allein der methoden name is schon genial 😃



  • Nein, tut er nicht.



  • Wenn "irgendwas" eine lokale Variable ist, ist es aber okay.



  • my best schrieb:

    Wenn "irgendwas" eine lokale Variable ist, ist es aber okay.

    jo. klar. hmm...

    naja, ohne meinen allocator könnte ich ja auf delete-this verzichten. aber egal. der allocator ist zu geil.



  • @MrN
    Bei mir wars damals der fall, dass ich noch die adresse des nächsten elements zurückgeben musste, bevor das objekt zerstört wird. Von daher sah das inetwa so aus:

    liste::delete(/*...*/)
    {
    /* ... */
     delete this;
     return MyNext;
    }
    

    damit die objekete auch noch ausgekoppelt werden konnten bevor sie sichzerstöhren.

    PS:
    hm, MyNext war n Private Atribut, also dürfte es obiges problem doch noch auslösen.
    Naja, speicher ich mir das vor dem delete this nochmal lokal.



  • THE_FreaK schrieb:

    Naja, speicher ich mir das vor dem delete this nochmal lokal.

    jo, gute idee 🙂



  • Also ich habe die Erfahrung gemacht, dass delete this ldiglich die Attribute der Klasse betrifft.
    D.h. dass man theoretisch folgendes machen kann, wenn die Klasse keine Attribute hat:

    Klasse* pC = 0;
    pC->foo();
    

    Jedenfalls gibt es bei VC keine Probleme damit.

    MfG MAV



  • hrhr, bei virtuellen methoden wär das lustig. ich denke aber, im allgemeinen hat iso über sowas ub verhängt.


Anmelden zum Antworten