Smart Pointer und Destruktoren



  • class A soll einen Baum symbolisieren, z.B. einen AST für mathematische Ausdrücke. inner() könnte eine simplify-Funktion sein, die z.B. 5*1 in 5 umwandelt.

    Dein Lösungsvorschlag hatte ich auch schon ausprobiert, er funktioniert aber nicht wenn du das 'a' aus Zeile 24 durch 'shared_ptr<A>(this);' ersetzt (das würde z.B. bei dem Ausdruck 5+1 eintreten, wenn dieser nicht weiter zu 6 vereinfacht werden soll).



  • Antoras schrieb:

    Dein Lösungsvorschlag hatte ich auch schon ausprobiert, er funktioniert aber nicht wenn du das 'a' aus Zeile 24 durch 'shared_ptr<A>(this);' ersetzt (das würde z.B. bei dem Ausdruck 5+1 eintreten, wenn dieser nicht weiter zu 6 vereinfacht werden soll).

    Naja, man darf halt nur Sachen dem shared_ptr geben, die der shared_ptr auch löschen soll. Aber ich verstehe das Problem.

    Eine mögliche Lösung ist eine Kopie zu machen:

    class C : public A {
    private:
        shared_ptr<A> a;
    public:
        C(A* a) : a(a){
        }
        explicit C(C &other) : a(other.a){
        }
        ~C(){
            cout << "dtor: C(" << this << ")" << endl;
            //delete a;
        }
        shared_ptr<A> inner() override{
            return C(*this); //Zeile 24 //nicht das * vergessen, sonst gibts segfaults!
        }
    };
    

    Es fühlt sich alles andere als optimal an.



  • Ich sollte auch schreiben was ich meine. Zeile 24 muss *return new C(this); heißen.



  • Komplett richtig ist wohl 'shared_ptr<A>(new C(*this));' 😉

    Das funktioniert jetzt endlich mal, danke!

    Ich habe mir schon gedacht, dass es irgendwie auf zwei Lösungen rausläuft: Entweder alle neu benötigten Teiles des Baums kopieren, oder aber sich irgendwie eine kleine mini Speicherverwaltungseinheit schreiben, die sich merkt was schon frei gegeben ist und was nicht und dann nur noch über diese Speicherverwaltungseinheit den Speicher freigeben lassen. Ersteres ist nicht effizient, aber für meine Zwecke vorerst ausreichend. Und letzteres ist mir zu aufwendig zu implementieren.

    Btw, wofür wird der Stern in 'new C(*this)' benötigt?



  • Der Stern dereferenziert den this Pointer. So wird der Kopierkonstruktor von C aufgerufen.



  • Weil Klasse C zwei Konstruktoren hat. Einer nimmt ein *A a, was ein neues C als Elternknoten von dem übergebenen a im Baum erzeugt, der andere nimmt ein C &c, was eine Kopie des Knoten machen soll. Das this ist ein *A **, also würde inner bei return new C(this) einen neuen Elternknoten von sich selbst erzeugen, während *this ein C ist (kein Zeiger) und eine Kopie erzeugt. Das sollte man unbedingt auseinander halten. Es sollte einen Syntaxfehler geben wenn man es falsch macht, wahrscheinlich sollte man statt eines Konstruktors lieber eine Memberfunktion copy oder so benutzen, damit man das Sternchen nicht vergessen kann.



  • evtl hilft dir auch eine fertige implementierung für kopierbare smart-pointer wie zb diese hier. mit shared_ptr würde ich nur dinge verwalten, die tatsächlich geteilt werden.



  • ok, danke nochmal für alle Antworten. Eine externe Lib werde ich jetzt noch nicht verwenden, ich schaue erst mal wie weit ich mit den std Bordmitteln komme.



  • shared_ptr hat in einem Graphen nichts zu suchen.



  • Kellerautomat schrieb:

    shared_ptr hat in einem Graphen nichts zu suchen.

    Es spricht nichts dagegen, in einem DAG shared_ptrs zu verwenden.


Anmelden zum Antworten