Direkt zum Hauptinhalt springen
eLearner.app
Modul 7 · Lektion 2 von 216/18 im Kurs~12 min
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.

Code
#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:

  1. Überprüfen, ob sie noch gültig ist, indem wir expired() aufrufen.
  2. Den weak_ptr temporär über die Methode lock() in einen shared_ptr umwandeln. Wenn die Ressource noch aktiv ist, gibt lock() einen gültigen shared_ptr zurück, andernfalls einen Null-Zeiger (nullptr).
Code
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

Übung#cpp.m7.l2.e1
Versuche: 0Wird geladen…

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.

Editor wird geladen…
Hinweis anzeigen

Deklariere den `weak_ptr` mit demselben generischen Typ `<int>` und weise ihm direkt `sPtr` zu.

Lösung nach 3 Versuchen verfügbar

Übung#cpp.m7.l2.e2
Versuche: 0Wird geladen…

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.

Editor wird geladen…
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