Lektionen des Moduls (2/2)
std::weak_ptr
Obwohl std::shared_ptr äußerst nützlich ist, kann die ausschließliche Verwendung von gemeinsamem Besitz zu einem Problem führen, das als zirkuläre Referenz (oder zyklische Abhängigkeit / cyclic dependency) bekannt ist.
Wenn zwei oder mehr Objekte jeweils einen shared_ptr enthalten, der auf das andere zeigt, entsteht eine geschlossene Schleife. In dieser Situation sinkt der Referenzzähler keines der beiden Objekte jemals auf Null, was die Freigabe des Speichers verhindert und ein Speicherleck (memory leak) verursacht.
Was ist std::weak_ptr?
Um Besitzzyklen zu durchbrechen, bietet die Standardbibliothek std::weak_ptr an. Dabei handelt es sich um einen intelligenten Zeiger, der ein von einem shared_ptr verwaltetes Objekt beobachtet, ohne den Referenzzähler zu erhöhen.
Er besitzt die Ressource nicht direkt, verhindert also auch nicht deren Zerstörung.
#include <memory>
std::shared_ptr<int> shared = std::make_shared<int>(42);
std::weak_ptr<int> weak = shared; // Non incrementa il contatore!
Überprüfung und Zugriff auf die Ressource
Da ein weak_ptr die Ressource nicht besitzt, kann sie jederzeit freigegeben werden (wenn alle damit verknüpften shared_ptr ihren Gültigkeitsbereich verlassen).
Um die beobachtete Ressource zu verwenden, müssen wir zuerst:
- Überprüfen, ob sie noch gültig ist, indem wir
expired()aufrufen. - Den
weak_ptrtemporär über die Methodelock()in einenshared_ptrumwandeln. Wenn die Ressource noch aktiv ist, gibtlock()einen gültigenshared_ptrzurück, andernfalls einen Null-Zeiger (nullptr).
if (!weak.expired()) {
// lock() crea uno shared_ptr temporaneo per garantire l'accesso sicuro
if (std::shared_ptr<int> sharedAccess = weak.lock()) {
std::cout << *sharedAccess << std::endl;
}
} else {
std::cout << "Risorsa deallocata!" << std::endl;
}
Probier es aus
Deklariere einen std::weak_ptr<int> namens wPtr, der ausgehend von sPtr initialisiert wird. Gib danach das von wPtr.expired() zurückgegebene boolesche Ergebnis mit std::cout aus.
Hinweis anzeigen
Deklariere den `weak_ptr` mit demselben generischen Typ `<int>` und weise ihm direkt `sPtr` zu.
Lösung nach 3 Versuchen verfügbar
Verwende die Methode lock() auf wPtr, um einen temporären shared_ptr zu erhalten. Wenn die Operation erfolgreich ist (der Zeiger also nicht Null ist), gib den dereferenzierten Wert auf dem Bildschirm aus.
Hinweis anzeigen
Initialisiere eine Variable innerhalb eines `if`-Blocks, indem du `wPtr.lock()` aufrufst, und gib dann die Ressource aus, indem du sie mit dem Sternchen `*` dereferenzierst.
Lösung nach 3 Versuchen verfügbar