Destruktoren- Klarrheit schaffen



  • A ist natürlich nicht so simpel wie hier dargestellt. Ich benutze obiges Prinzip der maps an verschiedenen Stellen mit verschiedenen Klassen.

    An einer Stelle wird z.B. die map mit einer abstrakten Oberklasse befüllt (könnte man wohl auch als Interface bezeichnen?!). Da muss ich mit Zeigern arbeiten und kann die Objekte selber nicht reinstopfen!?:

    class A
    {
        virtual void meth() = 0;
    };
    class Klasse
    {
    public:
        map<string, A*> testmap;
    };
    

    Warum sollte ich vermeiden etwas im Heap zu erzeugen? Ist das Resourcen fressend(er)? Nun bin ich bisschen überfordert mit den ganzen ***_ptr. Was ist das Ziel bzw. Vorteile , wenn ich die benutze?



  • Stack ist schneller, weil Du nicht wie beim Heap eine Indirektion über Zeiger hast und Elemente auf dem Stack werden im Ggs. zum Heap automatisch aufgeräumt (Du brauchst kein delete).



  • Diese sogenannten Smart-Pointer haben den Sinn, dass du nicht selbst new und delete verwenden musst. Diese legen sich selbst auf dem Heap an und vernichten sich auch wieder sauber. Dabei gibt es verschiedenen Varianten die unterschiedliche Aufgaben erfüllen. Ein share_ptr hat z. B. eine interne Zählung und wird nur vom Heap freigegeben, wenn nichts mehr diesen verwendet.

    Die Smartpointer bieten dir natürlich zusätzliche Funktionalitäten welche dadurch auch langsamer sein können (nicht müssen) als normale Pointer.



  • Ah super, dann kommen wir dem ganzen doch schon näher :-).

    Nexus schrieb:

    Ich würds so zusammenfassen:

    C++98

    • Lokaler Besitz: scoped_ptr
    • Geteilter Besitz: shared_ptr
    • Transferierter Besitz: auto_ptr
    • In Containern: ptr_vector (u.a.)

    C++0x

    • Lokaler/transferierter Besitz: unique_ptr
    • Geteilter Besitz: shared_ptr
    • In Containern: unique_ptr oder ptr_vector (u.a.)

    und welchen davon sollte ich nun wann nehmen? Ich kann mir leider momentan nichts unter der Differenzierung "*** Besitz" vorstellen.



  • Der Besitzer eines Objektes, ist derjenige, der das Objekt löschen muss, meistens ist das die Klasse selbst, die das Objekt erzeugt hat.



  • Was ist dann ein lokaler Besitzer oder ein geteilter???



  • Lokal bedeutet, dass das Objekt am Ende des Scopes weggeräumt wird. Geteilt heißt, dass es mehrere shared_ptr zu dem Objekt geben kann. Das Objekt wird dann weggeräumt, wenn alle shared_ptr zu dem Objekt gelöscht werden 😉
    (Nebenbei gibt es auch noch weak_ptr, der allerdings nicht so oft gebraucht wird, am besten siehst du im Internet nach, was er tut 😉



  • 314159265358979 schrieb:

    (Nebenbei gibt es auch noch weak_ptr, der allerdings nicht so oft gebraucht wird, am besten siehst du im Internet nach, was er tut 😉

    weak_ptr wird immer nur in Verbindung mit shared_ptr benutzt, er ist kein eigenständiger Smart-Pointer. Das sieht man daran, dass er keine Dereferenzierung anbietet.

    Und Absolute_nooby: shared_ptr brauchst du sehr selten. Wiederhole nicht den Fehler vieler C++-Programmierer und setze ihn aus Bequemlichkeit ein, zum Beispiel innerhalb STL-Container für automatische Wegräumung, wenn du viel lieber Pointer-Container nehmen würdest. Du solltest immer auch bedenken, dass er mit seinen vielen Features auch einiges an Laufzeitoverhead mitbringt.



  • 314159265358979 schrieb:

    Lokal bedeutet, dass das Objekt am Ende des Scopes weggeräumt wird. Geteilt heißt, dass es mehrere shared_ptr zu dem Objekt geben kann. Das Objekt wird dann weggeräumt, wenn alle shared_ptr zu dem Objekt gelöscht werden 😉
    (Nebenbei gibt es auch noch weak_ptr, der allerdings nicht so oft gebraucht wird, am besten siehst du im Internet nach, was er tut 😉

    Laut wikipedia ist Scope der Sichtbarkeitsbereich?! Würde das Beispiel stimmen:

    class A;
    meth()
    {
        A* a = new A();
        a->do1();
        a->do2();
        //...
    }// mit Abschluss der meth() wird der Scope verlassen?! Nun würde mit lokalem Pointer a aus dem Heap entfernt?!
    

    Was ist genau ein Container (im Bezug auf den ptr_vector)? Da war google nicht so wirklich aufschlussreich...



  • Du musst das Objekt in einen scoped_ptr werfen, dann wird es entfernt. Rohe Zeiger sind ziemlich dumm.
    std::vector, std::list, std::map sind Container. Du kannst darin mehrere Elemente des selben Typs speichern.



  • Du kannst das ja mal ausprobieren. Du benötigst dafür aber boost.

    #include <boost/scoped_ptr.hpp>
    #include <iostream>
    
    class A{public: void do1(){} void do2(){} ~A(){std::cout << "Destructor\n";}};
    
    void methdumb() 
    { 
        A* a = new A(); 
        a->do1(); 
        a->do2(); 
    
        delete a; //muss aufgerufen werden, sonst Memory leak!
    }
    
    void methsmart() 
    { 
    	boost::scoped_ptr<A> a(new A); 
        a->do1(); 
        a->do2(); 
    
        //Scoped ptr gibt hier automatisch die Ressource wieder frei! Kein Memory leak.
    	//Grund Destructor des scoped_ptr löscht mit delete.
    }
    


  • Absolute_nooby schrieb:

    Laut wikipedia ist Scope der Sichtbarkeitsbereich?! Würde das Beispiel stimmen:

    class A;
    meth()
    {
        A* a = new A();
        a->do1();
        a->do2();
        //...
    }// mit Abschluss der meth() wird der Scope verlassen?! Nun würde mit lokalem Pointer a aus dem Heap entfernt?!
    

    Falls dich die anderen Antworten verwirren: Pointer haben keine Sonderbehandlung. Der Pointer a liegt wird korrekt und richtig gelöscht. a liegt nämlich auf dem Stack. Aber das Objekt, auf das a zeigt, wird nicht gelöscht, weil es nicht der automatischen Speicherklasse unterliegt (es liegt auf dem Heap).
    Und genau hier kommt sowas wie scoped_ptr ins Spiel. Der verhält sich wie ein Pointer, löscht aber in seinem Destruktor sein referenziertes Objekt. Mit diesem "Trick" kann man also nicht-automatische Objekte an die automatische Speicherklasse binden. Diese Technik nennt sich RAII und ist ein Schlüsselparadigma von C++.


Anmelden zum Antworten