Frage

boost::shared_ptr hat eine ungewöhnliche Konstruktor

template<class Y> shared_ptr(shared_ptr<Y> const & r, T * p);

, und ich bin ein wenig verwirrt darüber, was dies für sinnvoll wäre. Grundsätzlich teilt es Eigentum mit r, aber .get() wird p zurück. nicht r.get()!

Dies bedeutet, dass Sie etwas tun können:

int main() {
    boost::shared_ptr<int> x(new int);
    boost::shared_ptr<int> y(x, new int);

    std::cout << x.get() << std::endl;
    std::cout << y.get() << std::endl;

    std::cout << x.use_count() << std::endl;
    std::cout << y.use_count() << std::endl;
}

Und Sie werden diese:

0x8c66008
0x8c66030
2
2

Beachten Sie, dass die Zeiger sind getrennt, aber sie behaupten, sowohl eine use_count von 2 haben (da sie das Eigentum an dem gleichen Objekt teilen).

Also, die int von x Besitz wird solange x existieren oder y um ist. Und wenn ich die Dokumentation richtig verstehen, wird die zweite int nie zerstört. Ich habe dies mit dem folgende Testprogramm bestätigt:

struct T {
    T() { std::cout << "T()" << std::endl; }
    ~T() { std::cout << "~T()" << std::endl; }
};

int main() {
    boost::shared_ptr<T> x(new T);
    boost::shared_ptr<T> y(x, new T);

    std::cout << x.get() << std::endl;
    std::cout << y.get() << std::endl;

    std::cout << x.use_count() << std::endl;
    std::cout << y.use_count() << std::endl;
}

Diese gibt (wie erwartet):

T()
T()
0x96c2008
0x96c2030
2
2
~T()

Also ... was ist der Nutzen dieses ungewöhnlichen Konstrukts, das Eigentum an einem Zeiger teilt, aber wirkt wie ein zweiten Zeiger (was sie nicht besitzen), wenn verwendet.

War es hilfreich?

Lösung

Es ist nützlich, wenn Sie einen Teilnehmer, und eine Instanz der Klasse teilen wollen, ist bereits ein shared_ptr, wie folgt aus:

struct A
{
  int *B; // managed inside A
};

shared_ptr<A>   a( new A );
shared_ptr<int> b( a, a->B );

sie die Verwendung Zahl und Sachen teilen. Es ist die Optimierung für die Speichernutzung.

Andere Tipps

Leiz zu erweitern und Piotrs Antworten, diese Beschreibung von shared_ptr<> ' Aliasing‘ist aus einem WG21 Papier, "Die Verbesserung der shared_ptr für C ++ 0x, Revision 2" :

  

III. Aliasing Unterstützung

     

Fortgeschrittene Benutzer erfordern oft die   Fähigkeit, eine shared_ptr zu erstellen   Beispiel p, dass das Eigentum teilt mit   Weitere (Master) shared_ptr q aber   auf ein Objekt, das nicht eine Base   von *q. *p kann ein Mitglied oder eine   Element *q, zum Beispiel. Diese   Abschnitt schlägt eine zusätzliche   Konstruktor, der dafür verwendet werden kann,   Zweck.

     

Ein interessanter Nebeneffekt dieser   Steigerung der Ausdruckskraft ist, dass   jetzt die *_pointer_cast Funktionen können   werden in Benutzercode implementiert. Das   make_shared Fabrik Funktion vorgestellt   später in diesem Dokument kann auch sein,   implementiert nur die Öffentlichkeit mit   Schnittstelle von shared_ptr über das   Aliasing-Konstruktor.

     

Auswirkungen:

     

Diese Funktion erweitert die Schnittstelle von   shared_ptr in einer rückwärtskompatibel   Art und Weise, die ihren Ausdruck erhöht   Leistung und ist daher stark   empfohlen, die C ++ 0x hinzugefügt werden   Standard. Es führt keine Quellen- und   binäre Kompatibilitätsprobleme.

     

Textvorschlag:

     

In den shared_ptr   [Util.smartptr.shared] die folgende   Konstruktor:

     
template<class Y> shared_ptr( shared_ptr<Y> const & r, T * p );
  
     

Fügen Sie Folgendes   [Util.smartptr.shared.const]:

     
template<class Y> shared_ptr( shared_ptr<Y> const & r, T * p );
         

Effekte: Konstruiert eine shared_ptr Instanz, die p und Aktien Eigentum mit r speichert

.          

Nachbedingungen:. get() == p && use_count() == r.use_count()

         

Wirft:. nichts

         

[Anmerkung: , um die Möglichkeit eines baumelnden Zeiger zu vermeiden, den Benutzer     dieser Konstruktor muss, dass p gewährleisten bleibt gültig mindestens     bis die Eigentümergruppe r zerstört. -. Endnote]

         

[Hinweis: Dieser Konstruktor ermöglicht die Erstellung eines leer shared_ptr     Beispiel mit einem nicht-NULL-Zeiger gespeichert. -. Endnote]

  

Sie können dies auch dynamische gegossene Zeiger zu halten verwenden, das heißt:.

class A {};
class B: public A {};

shared_ptr<A> a(new B);
shared_ptr<B> b(a, dynamic_cast<B*>(a.get()));

Sie können einen Zeiger auf einen Fahrer oder ein niedrigeren Datenstruktur Niveau api, die von seiner unteren Ebene api oder anderen Mitteln zusätzliche Daten zuordnen kann. In diesem Fall könnte es interessant sein, die use_count zu erhöhen, aber die zusätzlichen Daten zurück, wenn der erste Zeiger die anderen Datenzeiger besitzt.

Ich habe Shared_ptr des Aliasing-Konstruktor in Gebrauch in meiner kleinen Bibliothek setzen:

http://code.google.com/p/infectorpp/ (nur meine einfache IoC-Container)

Der Punkt ist, dass, da ich ein shared_ptr bekannten Art benötigt, um von einer polymorphen Klasse zurückgegeben werden (also nicht die Art nicht kennt). Ich war nicht in der Lage, implizit die shared_ptr auf den Typ zu umwandeln ich brauchte.

In der Datei „ InfectorHelpers.hpp “(Zeile 72-99) können Sie, dass in Aktion für den Typen siehe IAnyShared.

Aliasing-Konstruktor erstellt shared_ptr, die nicht die Zeiger löscht sie tatsächlich zeigt auf, sondern sie noch den Referenzzähler erhöhen auf das ursprüngliche Objekt und das kann enorm nützlich sein.

Grundsätzlich können Sie einen Zeiger auf etwas schaffen mit Aliasing-Konstruktor und Bedrohung als Referenzzähler.

//my class
std::shared_ptr<T> ist;
int a; //dummy variable. I need its adress

virtual std::shared_ptr<int> getReferenceCounter(){
    return std::shared_ptr<int>(ist,&a); //not intended for dereferencing
}

virtual void* getPtr(); //return raw pointer to T

Jetzt haben wir beide „einen Referenzzähler“ und einen Zeiger auf eine istance von T, genug Daten etwas mit dem Aliasing-Konstruktor erstellen

std::shared_ptr<T> aPtr( any->getReferenceCounter(), //share same ref counter 
               static_cast<T*>(any->getPtr()) ); //potentially unsafe cast!

Ich behaupte nicht, diese Verwendung für das Aliasing-Konstruktor erfunden zu haben, aber ich habe nie jemand anderes tut das gleiche gesehen. Wenn Sie erraten, wenn die schmutzige Code funktioniert die Antwort ja.

"shared_ptr<B> b(a, dynamic_cast<B*>(a.get()));"

Ich denke, es ist nicht der empfohlene Weg Smart-Pointer verwendet wird.

Es wird empfohlen, diese Art Umwandlung tun sollte:

shared_ptr<B> b(a);

Da in Boost-Dokument wird erwähnt, dass:

  

shared_ptr<T> kann implizit sein   umgerechnet auf shared_ptr<U> T, wenn *   implizit in U * umgewandelt werden. Im   Insbesondere shared_ptr<T> ist   implizit konvertierbar shared_ptr<T> const,   shared_ptr<U> wobei U ein ist,   zugänglich Basis von T, und   shared_ptr<void>.

Neben dem haben wir auch dynamic_pointer_cast die auf Smart Pointer-Objekt und beide diese beiden Methoden wäre viel sicherer als die von Hand Gießen Rohzeiger Art und Weise direkt Umwandlung tun könnte.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top