Fragen zu Boost smart-pointern



  • Xebov schrieb:

    Sehe ich das Richtig das es ansich absolut keinen Weg gibt dem Smart-Pointer den anvertrauten Zeiger zu entreißen?

    Du kannst zwar über get() auf den rohen Zeiger zugreifen, jedoch solltest du das normalerweise nicht tun. Was auch wichtig ist: Wenn mehrere shared_ptr s ein gemeinsames Ziel haben, solltest du nur einen direkt mit dem rohen Zeiger initialisieren. Die anderen kopierst du davon. Das ist nötig, damit die Referenzzählung richtig funktioniert.

    Xebov schrieb:

    Also das man in jedem Fall bei eienr Änderung des Smart-Pointers ein Löschen des Alten Zeigers hinnehmen muß (sofern auch der Referenzcounter hinhaut)?

    Du sprichst jetzt von shared_ptr . Wenn du den Zeiger umhängst, wird geschaut, ob auf den alten Speicher noch mindestens ein anderer shared_ptr zeigt. Falls nein, wird der Speicher freigegeben.

    Xebov schrieb:

    Würde es in so einem Beispiel überhaupt Sinn machen das ganze extra in einen Smartpointer zu stecken?

    Wie volkard erwähnt hat, machen Smart Pointers oft Sinn, wenn nicht klar ist, wer freigibt. Zum Beispiel wenn eine Funktion an x Stellen verlassen werden kann (u.a. mit Exceptions) und du nicht x Mal delete haben willst. Der scoped_ptr ist ein Smart Pointer, der beim Verlassen des Gültigkeitsbereiches freigibt. Dieser hat kaum Overhead gegenüber einem rohen Zeiger, sodass sich der Einsatz schnell auszahlt. Allerdings sollte man es trotzdem nicht übertreiben. Wenn eine Klasse verhältnismässig triviale Speicherverwaltung hat (Anfordern in Konstruktoren, Freigeben in Destruktor), kann man ruhig new und delete verwenden.

    Xebov schrieb:

    Und meine letzte Frage. Funktioniert mit den Smart-Pointern überhaupt folgendes Szenario?

    Es gibt zwar "Smart-Arrays" ( shared_array , scoped_array ), aber das scheint mir hier nicht der richtige Ansatz. In deinem Fall würde ich eher Container nehmen.



  • Ok danke für die Ausführlichen Antworten. Wenn ich das richtig verstehe kann ich die Smart-Pointer auch nicht als Temporären Schutz einsetzen oder? Also nach folgendem Muster, eine Klasse hat einen Speicherbereich mit new, um das erstellen und löschen kümemrn sich Konstruktor und Destruktor. Es gibt eine Funktion die den Speicherbereich evrgrößert und einen neuen anlegt ihn kopiert und den alten löscht. In so eienr Klasse würde ja ganz klar die Klasse selbst alles übernehmen, aber in der vergrößerungsfunktion wäre ja ein Smartpointer nicht shclecht um den neuen Speicherbereich Temporär zu halten, falls es zu fehlern komtm so das er garanteirt gelöscht wird. Hier ginge es dann wohl nur über einen Swap so das man dem Smart-Pointer nach erfolg den Alten zeiger andreht so das er diesen löscht da man den neuen nicht mehr aus ihm rausbekommt?



  • Was du hier suchst ist std::vector. Ein resize() wuerde etwa so aussehen:

    void vector::resize(size_type newSize) {
      vector temp(newSize);
      temp.assign(*this);
      swap(*this, temp);
    }
    

    sprich du fasst rohen speicher einfach nicht an. smart_ptr sind dafuer da, wenn die besitzverhaeltnisse nicht klar sind, die loeschung des speichers zu uebernehmen. aber generell braucht man rohen speicher sowieso fast nie anzufassen...



  • Ja das ginge auch mich würde aber trotzdem interessieren ob das oben von mir geschriebene so gehen würde.



  • Xebov schrieb:

    Ok danke für die Ausführlichen Antworten. Wenn ich das richtig verstehe kann ich die Smart-Pointer auch nicht als Temporären Schutz einsetzen oder? Also nach folgendem Muster, eine Klasse hat einen Speicherbereich mit new, um das erstellen und löschen kümemrn sich Konstruktor und Destruktor. Es gibt eine Funktion die den Speicherbereich evrgrößert und einen neuen anlegt ihn kopiert und den alten löscht. In so eienr Klasse würde ja ganz klar die Klasse selbst alles übernehmen, aber in der vergrößerungsfunktion wäre ja ein Smartpointer nicht shclecht um den neuen Speicherbereich Temporär zu halten, falls es zu fehlern komtm so das er garanteirt gelöscht wird. Hier ginge es dann wohl nur über einen Swap so das man dem Smart-Pointer nach erfolg den Alten zeiger andreht so das er diesen löscht da man den neuen nicht mehr aus ihm rausbekommt?

    doch, da sieht man smart pointers öfters. kennste auch die sorte auto_pointer?
    http://www.cplusplus.com/reference/std/memory/auto_ptr/release/
    aber die smart-pointer-variante beim wachsen müßte man wegen exceptionunsicherheit wohl als falsch bewerten.
    aber sagen wir mal die klasse hat zwei mit new anzulegende members, dann kannste das erste gut mit nem auto_ptr festhalten, dann das zweite attribut zuweisen, dann das erste aus dem auto_pointer.release() füttern. rein theoretisch. im ctor brauchste das nicht, wenn du initialisiererlisten benutzt. und mit dem copy&swap brauchst du es woanders auch nicht. komisch. aber irgendwo hab ich das mal so ähnlich gesehen. ich habe schon lange lange keine smart pointers mehr benutzt.

    mit dem swappen haste aber insofern recht, daß man da swappt. nur halt ohne smartpounter.
    legst einfach ein neues objekt deiner klasse an, befüllste sie mit den daten uns swapst.

    vector::grow(){
      vector tmp(size()*2);
      for each e in *this
        tmp.push_back(e);
      swap(*this,tmp);
    }
    

    das klappt nämlich auch, wenn beim op= des fünfzigsten elements eine exception fliegt.



  • volkard schrieb:

    doch, da sieht man smart pointers öfters. kennste auch die sorte auto_pointer?
    http://www.cplusplus.com/reference/std/memory/auto_ptr/release/

    Ne da skannte ich nicht sieht abe rganz gut aus.

    volkard schrieb:

    aber die smart-pointer-variante beim wachsen müßte man wegen exceptionunsicherheit wohl als falsch bewerten.

    Wieso?

    int *pMyMember;
    void Enlarge()
    {
        SmartPointer pNewPointer(new int);
        Copy pMyMember to pNewPointer;
      Entweder:
        delete[] pMymember;
        pMyMember=inhalt pNewPointer;
        pNewPointer=Null;
      Oder:
        Swap pNewPoinetr pMyMember
    };
    

    Wäre doch eigentlich beides Exceptionsicher, auch wenn beide Varianten mit den Boost Pointern wohl eh nicht gehen.



  • Xebov schrieb:

    volkard schrieb:

    aber die smart-pointer-variante beim wachsen müßte man wegen exceptionunsicherheit wohl als falsch bewerten.

    Wieso?

    int *pMyMember;
    void Enlarge()
    {
        SmartPointer pNewPointer(new int);
        Copy pMyMember to pNewPointer;
    
        delete[] pMymember;
        pMymember=inhalt Smartpointer
    };
    

    mir scheint, du hast nicht rohen speocher angefordert und per placement new dorthineinkonstruiert. davon hing ich hingegen aus.



  • Also ind em Beispiel ist natürlich vorausgesetzt das der Int-zeiger Speicher hält usw.

    Nein ich hole mir meinen Speiche rimemr Häppchenweise wenn ich dich richtig verstehe gingst du davon aus, das ich mir einmal nen großen Brocken am Programmstart hole und ihn dann selbst Verteile?



  • Xebov schrieb:

    Also ind em Beispiel ist natürlich vorausgesetzt das der Int-zeiger Speicher hält usw.

    Nein ich hole mir meinen Speiche rimemr Häppchenweise wenn ich dich richtig verstehe gingst du davon aus, das ich mir einmal nen großen Brocken am Programmstart hole und ihn dann selbst Verteile?

    nein, auch häppchenweise.
    sagen wie mal zu angang 100 ints. und dann bei jedem wachsen verdoppeln.
    jedes push_back belegt einen weiteren meiner anfanhs 100 plätzchen. klappt ein push_back nicht, weils voll ist, muß halt gewachsen werden.
    und um nicht nur ints als elemente verwalten zu könnenm das dann als template. und weil die elemente evtl teuer zu konstruoeren sind, konstruierte ich erst im push_back per placement-new.



  • Ah ok jetzt evrstehe ich wie du das meisnt, so mache ich es nicht, also ich hole mir den Platz und Konstruiere gleich alles. Für mich ist halt etwas im Sinen meines Beispiels gefragt aber der auto_ptr scheint dafür ja ganz gut geeignet zu sein um mal temporär was zu halten.


Anmelden zum Antworten