shared_ptr: Wer nutzt sie wirklich?!



  • Ich stolper in letzter Zeit immer wieder über Projekte, in denen shared_ptr exzessiv genutzt werden. Auch das aktuelle Projekt, an dem ich arbeite, nutzt ausschließlich shared_ptr.

    Davon abgesehen, dass ich die syntaktisch furchtbar finde, finde ich auch, dass das der eigentliche Sinn oft nicht gegeben ist.

    Wenn ich tatsächlich etwas mit new anfordere, muss ich es später wieder freigeben. Wie kann es sein, dass niemand mehr weiß, wann das sein soll, weil ein Pointer über 17 Klassen verteilt wird?

    Mein Ansatz war bisher: Der Erzeuger löscht am Ende. Alle Klassen, die dass Objekt nutzen, holen sich den Pointer und fertig.



  • GesharterContent schrieb:

    Mein Ansatz war bisher: Der Erzeuger löscht am Ende. Alle Klassen, die dass Objekt nutzen, holen sich den Pointer und fertig.

    Der "Erzeuger" will sich das Leben sicherlich einfach machen, in dem er einen unique_ptr behält oder in dieser Form die Verantwortung an jemanden anderen übertragen kann. Rohe Zeiger gleichzeitig irgendwo zu speichern kann aber gefährlich sein. Wenn vom Design her nicht sofort ersichtlich ist, dass die rohen Zeiger nie benutzt werden können, nachdem der besitzende unique_ptr verschwindet -- zum Beispiel bei einer Baumstruktur, wo ein Elter die Kinder besitzt und die Kinder den Elter über einen rohen Zeiger erreichen -- kannst Du Dir ggf. einen Use-After-Free Fehler einhandeln. Mit shared_ptr + weak_ptr statt unique_ptr + roher Zeiger könnte man immerhin zur Laufzeit diesen Fehler erkennen, siehe weak_ptr::expired und weak_ptr::lock.



  • GesharterContent schrieb:

    Ich stolper in letzter Zeit immer wieder über Projekte, in denen shared_ptr exzessiv genutzt werden. Auch das aktuelle Projekt, an dem ich arbeite, nutzt ausschließlich shared_ptr.

    Ja, leider ist das oft so.

    GesharterContent schrieb:

    Mein Ansatz war bisher: Der Erzeuger löscht am Ende. Alle Klassen, die dass Objekt nutzen, holen sich den Pointer und fertig.

    Wenn dabei make_unique und unique_ptr verwendet wird, ist das häufig der richtige Weg (in der Annahme Erzeuger ist = Eigentümer, muss ja nicht zwingend so sein). new und vor allem delete sollten in neuem Code im Regelfall nicht vorkommen.



  • Ein shared_ptr macht immer genau dann Sinn, wenn mehr als ein Client auf genau ein Object zugreifen und im Vorfeld nicht definiert werden kann, wann der letzte Client stirbt.
    Und genau das ist bei den Projekten, an denen ich arbeite, alle Nase lang der Fall. Das Erzeugen des Objekts geschieht oft über eine externe Factory, die dann im weiteren Verlauf nichts mehr damit zu tun hat.

    Weiter benötige ich den shared_ptr auch dann, wenn ich einen costum-Deleter dort unterbringen möchte, aber den Typ des Pointers nicht von diesem Deleter abhängig machen will.

    Ich gebe Dir Recht, dass vielleicht mancher shared_ptr durch einen unique_ptr ersetzt werden könnte. Ich habe aber in den letzten Jahren eher die Erfahrung gemacht, dass ich oft mit einem unique_ptr beginne und dann im Laufe der Implementierung aus gewichtigen Gründen (s.o.) daraus doch einen shared_ptr mache.

    manni66 schrieb:

    new und vor allem delete sollten in neuem Code im Regelfall nicht vorkommen.

    Das sehe ich genauso.

    Dass der shared_ptr so überhand nehmen kann, kann auch historische Gründe haben. Die erste praxisnahe und verbreitete Implementierung war der boost::shared_ptr und das ist ein Fits-All-Ding. (s. golden hammer antipattern)

    Ich kann mir auch Projekte vorstellen, in denen man keinen shared_ptr benötigt, aber gesehen habe ich noch keines.

    Gruß
    Werner



  • Werner Salomon schrieb:

    Ich kann mir auch Projekte vorstellen, in denen man keinen shared_ptr benötigt, aber gesehen habe ich noch keines.

    So rein des Interesses wegen: Was ist das denn für eine Anwendungsdomäne?


Anmelden zum Antworten