Aus dem Artikel von Dr. Dobbs über schwache Zeiger geht hervor, dass dieses Beispiel leichter zu verstehen ist (Quelle: http://drdobbs.com/cpp/184402026 ):
... Code wie dieser funktioniert nicht richtig:
int *ip = new int;
shared_ptr<int> sp1(ip);
shared_ptr<int> sp2(ip);
Keines der beiden shared_ptr
Objekte kennt das andere, daher versuchen beide, die Ressource freizugeben, wenn sie zerstört werden. Das führt normalerweise zu Problemen.
Wenn eine Mitgliedsfunktion ein shared_ptr
Objekt benötigt, das das Objekt besitzt, für das sie aufgerufen wird, kann sie nicht einfach ein Objekt im laufenden Betrieb erstellen:
struct S
{
shared_ptr<S> dangerous()
{
return shared_ptr<S>(this); // don't do this!
}
};
int main()
{
shared_ptr<S> sp1(new S);
shared_ptr<S> sp2 = sp1->dangerous();
return 0;
}
Dieser Code hat das gleiche Problem wie das vorherige Beispiel, allerdings in einer subtileren Form. Wenn es erstellt wird, besitzt das shared_pt
r-Objekt sp1
die neu zugewiesene Ressource. Der Code in der Member-Funktion S::dangerous
kennt dieses shared_ptr
Objekt nicht, daher unterscheidet sich das zurückgegebene shared_ptr
Objekt von sp1
. Das Kopieren des neuen shared_ptr
Objekts nach sp2
hilft nicht. Wenn sp2
der Gültigkeitsbereich verlassen wird, wird die Ressource freigegeben, und wenn sp1
der Gültigkeitsbereich verlassen wird, wird die Ressource erneut freigegeben.
Um dieses Problem zu vermeiden, verwenden Sie die Klassenvorlage enable_shared_from_this
. Die Vorlage verwendet ein Vorlagentypargument, bei dem es sich um den Namen der Klasse handelt, die die verwaltete Ressource definiert. Diese Klasse muss wiederum öffentlich aus der Vorlage abgeleitet werden. so was:
struct S : enable_shared_from_this<S>
{
shared_ptr<S> not_dangerous()
{
return shared_from_this();
}
};
int main()
{
shared_ptr<S> sp1(new S);
shared_ptr<S> sp2 = sp1->not_dangerous();
return 0;
}
Beachten Sie dabei, dass das Objekt, das Sie aufrufen shared_from_this
, einem shared_ptr
Objekt gehören muss. Das wird nicht funktionieren:
int main()
{
S *p = new S;
shared_ptr<S> sp2 = p->not_dangerous(); // don't do this
}