Intelligente Zeiger aus Funktion zurückgeben



  • Hallo liebe Forengemeinde,

    ich versuche zur Zeit einige wichtige Tipps von Scott Meyers "Effektiv C++ programmieren" in meinem Projekt zu beherzigen. Er schreibt in einem seiner Tipps, dass man mit new erzeugte Objekte in intelligenten Zeigern speichern soll.(Tipp 17)
    Ich befinde mich nun in einer Funktion, die ein neues Objekt erzeugt mit dem new-Operator: std::tr1::shared_ptr<Widget>pw(new Widget);
    Das Problem ist nun, dass shared_ptr selbst auch ein Objekt ist und nicht mit dem new-Operator erzeugt wurde, d.h. auf dem Stack. Somit ist es lokal. Wenn die Funktion nun in irgendeiner Weise dieses Objekt mit dem Zeiger in ihm zurückgibt, wird der Gültigkeitsbereich verlassen und der Pointer zerstört und damit auch der darin enthaltene Zeiger.
    Muss ich nun auch noch einen Zeiger auf shared_ptr definieren und dieses ebenfalls mit new erzeugen, damit es auf dem Heap erzeugt wird und dann zurückgegeben werden kann?
    Das wäre doch doppelt gemoppelt: ein Zeiger auf ein Objekt, dass einen Zeiger auf ein Objekt enthält.

    Habe ich da einen Denkfehler bzw. geht das auch einfacher?

    Danke für eure Hilfe 👍



  • Ohne das Buch zu haben, aber was wäre denn wenn du das so machst?

    return shared_ptr<new blah>;
    


  • Das Ganze ist kein Problem, wenn du aus der Funktion eine Kopie des Smartpointers zurückgibst. Das shared_ptr-Objekt innerhalb der Funktion wird zerstört, aber der Rückgabewert (die Kopie) lebt weiter.



  • Einen SmartPointer aufm FreeStore anzulegen (new), macht das ganze system des "smarten" pointers doch zunichte. Smartpointer sind doch per definition StackKlassen, die Freestore-zeiger verwalten.

    was passiert, bei einer Zuweisung bestimmt die semantik hinter dem Smartpointer.

    z.b. ein std::string ist von seiner Basis her eigentlich auch ein SmartPointer. und zwar auf irgend eine Folge von Zeichen in einem dyn. allokierten Speicherbereich.
    Das Ding hat eine Kopiersemantik, das heisst bei der Zuweissung wird der Inhalt von dem Speicher in einen Neuen bereich kopiert. Deshalb kannst das ding "problemlos" zurueckgeben.

    shared_pointer ist so definiert:

    A shared_ptr object effectively holds a pointer to the resource that it owns or holds a null pointer. A resource can be owned by more than one shared_ptr object; when the last shared_ptr object that owns a particular resource is destroyed, the resource is freed.

    A shared_ptr stops owning a resource when it is reassigned or reset.

    Das Object wird erzeugt ... und wenn es irgendwann mal keinen shared_pointer auf das Object geben kann, wird das Object zerstoert. Da du zugriff nur ueber einen Shared_pointer auf das Object bekommst, wird das Object zerstoert, wenn der letzte Smart_pointer auf das Object zerstoert oder umorganisiert wird.
    Meist werden die Dinger also mit referenzzaehlung implementiert.

    Ciao ...



  • BootLag-BootLag- schrieb:

    Hallo liebe Forengemeinde,

    ich versuche zur Zeit einige wichtige Tipps von Scott Meyers "Effektiv C++ programmieren" in meinem Projekt zu beherzigen. Er schreibt in einem seiner Tipps, dass man mit new erzeugte Objekte in intelligenten Zeigern speichern soll.(Tipp 17)
    Ich befinde mich nun in einer Funktion, die ein neues Objekt erzeugt mit dem new-Operator: std::tr1::shared_ptr<Widget>pw(new Widget);
    Das Problem ist nun, dass shared_ptr selbst auch ein Objekt ist und nicht mit dem new-Operator erzeugt wurde, d.h. auf dem Stack. Somit ist es lokal. Wenn die Funktion nun in irgendeiner Weise dieses Objekt mit dem Zeiger in ihm zurückgibt, wird der Gültigkeitsbereich verlassen und der Pointer zerstört und damit auch der darin enthaltene Zeiger.
    Muss ich nun auch noch einen Zeiger auf shared_ptr definieren und dieses ebenfalls mit new erzeugen, damit es auf dem Heap erzeugt wird und dann zurückgegeben werden kann?
    Das wäre doch doppelt gemoppelt: ein Zeiger auf ein Objekt, dass einen Zeiger auf ein Objekt enthält.

    Habe ich da einen Denkfehler bzw. geht das auch einfacher?

    Danke für eure Hilfe 👍

    Wenn du das Buch richtig und gewissenhaft gelesen hättest, hättest du sicherlich auch die Stelle gelesen, an der die Antwort auf deine Frage steht. Du kannst, wie hier auch schon von Anderen erläutert wurde, einfach einen shared_ptr zurückgeben.

    Lg freeG



  • Nya ich habe mich etwas umständlich ausgedrückt. In meinem Beispiel habe ich konkret eine globale Liste, in die in der Funktion shared_ptr-Objekte geworfen werden. Diese kann ich ja nun nicht ohne den new-Operator einfügen, da sie ja nach Funktionsrückgabe gelöscht werden. So war das gemeint



  • Die Liste speichert Kopien der shared_ptr-Objekte, die du hineinwirst (sofern es keine Liste von Zeigern auf shared_ptr oder etwas ähnlich seltsames ist). Das ist völlig unproblematisch.



  • OK hat geklappt! Danke schön


Anmelden zum Antworten