Frage Einen boost :: shared_ptr dafür bekommen


Ich mache ausgiebig Gebrauch davon boost:shared_ptr in meinem Code. Tatsächlich werden die meisten Objekte, die auf dem Heap zugewiesen sind, von a gehalten shared_ptr. Leider bedeutet das, dass ich nicht bestehen kann this in jede Funktion, die ein shared_ptr. Betrachten Sie diesen Code:

void bar(boost::shared_ptr<Foo> pFoo)
{
    ...
}

void Foo::someFunction()
{
    bar(this);
}

Hier gibt es zwei Probleme. Zuerst wird das nicht kompiliert, da der T * -Konstruktor für shared_ptr ist explizit. Zweitens, wenn ich es zwinge mit zu bauen bar(boost::shared_ptr<Foo>(this)) Ich habe einen zweiten gemeinsamen Zeiger auf mein Objekt erstellt, der schließlich zu einem doppelten Löschen führen wird.

Das bringt mich zu meiner Frage: Gibt es ein Standardmuster für das Abrufen einer Kopie des vorhandenen freigegebenen Zeigers, von dem Sie wissen, dass er in einer Methode für eines dieser Objekte vorhanden ist? Ist das Verwenden von intrusivem Referenzzählen meine einzige Option?


76
2017-09-26 22:42


Ursprung


Antworten:


Sie können von ableiten enable_shared_from_this und dann können Sie "shared_from_this ()" anstelle von "this" verwenden, um einen gemeinsamen Zeiger auf Ihr eigenes Selbstobjekt zu erzeugen.

Beispiel im Link:

#include <boost/enable_shared_from_this.hpp>

class Y: public boost::enable_shared_from_this<Y>
{
public:

    shared_ptr<Y> f()
    {
        return shared_from_this();
    }
}

int main()
{
    shared_ptr<Y> p(new Y);
    shared_ptr<Y> q = p->f();
    assert(p == q);
    assert(!(p < q || q < p)); // p and q must share ownership
}

Es ist eine gute Idee, wenn Sie Threads von einer Member-Funktion zu boost :: bind an eine shared_from_this () erzeugen. Dadurch wird sichergestellt, dass das Objekt nicht freigegeben wird.


102
2017-09-26 22:46



Verwenden Sie einfach einen rohen Zeiger für Ihren Funktionsparameter anstelle von shared_ptr. Der Zweck eines Smart-Zeigers ist es, die Lebensdauer des Objekts zu steuern, aber die Lebensdauer des Objekts ist bereits durch die C ++ - Scoping-Regeln garantiert: Sie existiert mindestens so lange wie das Ende Ihrer Funktion. Das heißt, der aufrufende Code kann das Objekt möglicherweise nicht löschen, bevor Ihre Funktion zurückkehrt. somit ist die Sicherheit eines "dummen" Zeigers gewährleistet, solange Sie nicht versuchen, das Objekt in Ihrer Funktion zu löschen.

Sie müssen ein shared_ptr nur dann an eine Funktion übergeben, wenn Sie das Objekt an die Funktion übergeben möchten oder die Funktion eine Kopie des Zeigers erstellen soll.


19
2017-09-27 03:59



Boost hat eine Lösung für diesen Anwendungsfall, überprüfen enable_shared_from_this


14
2017-09-26 22:44



Machst du wirklich mehr Kopien von pFoo in der Bar? Wenn du nichts Verrücktes im Inneren machst, tu folgendes:


void bar(Foo &foo)
{
    // ...
}

9
2017-09-26 23:07



Mit C ++ 11 shared_ptr und enable_shared_from_this ist jetzt in der Standardbibliothek. Letzteres ist, wie der Name schon sagt, für diesen Fall genau.

http://en.cppreference.com/w/cpp/memory/shared_ptr

http://en.cppreference.com/w/cpp/memory/enable_shared_from_this

Beispiel basiert auf dem in den Links oben:

struct Good: std::enable_shared_from_this<Good>{
    std::shared_ptr<Good> getptr() {
        return shared_from_this();
    }
};

benutzen:

std::shared_ptr<Good> gp1(new Good);
std::shared_ptr<Good> gp2 = gp1->getptr();
std::cout << "gp2.use_count() = " << gp2.use_count() << '\n';

5
2017-12-25 13:08



Die Funktion, die einen Zeiger akzeptiert, möchte eines von zwei Verhaltensweisen ausführen:

  • Besitze das Objekt übergeben werden, und löschen Sie es, wenn es den Gültigkeitsbereich verlässt. In diesem Fall können Sie einfach X * akzeptieren und sofort ein scoped_ptr um dieses Objekt (im Funktionskörper) legen. Dies wird funktionieren, um "dieses" oder im Allgemeinen jedes dem Heap zugewiesene Objekt zu akzeptieren.
  • Teilen Sie einen Zeiger (besitzen Sie es nicht) zu dem Objekt, das übergeben wird. In diesem Fall tun Sie nicht möchte überhaupt ein scoped_ptr verwenden, da das Objekt nicht am Ende der Funktion gelöscht werden soll. In diesem Fall ist das, was Sie theoretisch wollen, ein shared_ptr (ich habe es an anderer Stelle als linked_ptr bezeichnet). Die Boost-Bibliothek hat eine Version von shared_ptr, und dies wird auch in Scott Meyers effektivem C ++ Buch empfohlen (Punkt 18 in der 3. Ausgabe).

Bearbeiten: Ups, ich habe die Frage ein wenig falsch verstanden, und ich sehe jetzt, dass diese Antwort nicht genau auf die Frage eingeht. Ich werde es trotzdem weglassen, falls das für jemanden, der an ähnlichem Code arbeitet, hilfreich sein könnte.


3
2017-09-27 00:26