Przejdź do głównej treści
eLearner.app
Moduł 7 · Lekcja 2 z 216/18 w kursie~12 min
Lekcje modułu (2/2)

std::weak_ptr

Chociaż std::shared_ptr jest niezwykle użyteczny, wyłączne korzystanie z własności współdzielonej może prowadzić do problemu znanego jako referencja cykliczna (lub zależność cykliczna / cyclic dependency).

Jeśli dwa lub więcej obiektów zawiera shared_ptr wskazujący na siebie nawzajem, tworzy się zamknięty cykl. W takiej sytuacji licznik odwołań żadnego z obiektów nigdy nie spadnie do zera, co uniemożliwi zwolnienie pamięci i spowoduje wyciek pamięci (memory leak).

Czym jest std::weak_ptr?

Aby przerwać cykle własności, biblioteka standardowa oferuje std::weak_ptr. Jest to inteligentny wskaźnik, który obserwuje obiekt zarządzany przez shared_ptr, ale bez zwiększania licznika odwołań (reference count).

Nie posiada bezpośrednio zasobu, więc nie zapobiega jego zniszczeniu.

Code
#include <memory>

std::shared_ptr<int> shared = std::make_shared<int>(42);
std::weak_ptr<int> weak = shared; // Non incrementa il contatore!

Weryfikacja i dostęp do zasobu

Ponieważ wskaźnik weak_ptr nie posiada zasobu na własność, może on zostać zwolniony w dowolnym momencie (gdy wszystkie powiązane wskaźniki shared_ptr opuszczą zakres).

Aby skorzystać z obserwowanego zasobu, musimy najpierw:

  1. Sprawdzić, czy jest nadal ważny, używając expired().
  2. Tymczasowo przekonwertować weak_ptr na shared_ptr za pomocą metody lock(). Jeśli zasób jest nadal aktywny, lock() zwraca prawidłowy shared_ptr, w przeciwnym razie zwraca wskaźnik pusty (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;
}

Spróbuj sam

Ćwiczenie#cpp.m7.l2.e1
Próby: 0Ładowanie...

Zadeklaruj std::weak_ptr<int> o nazwie wPtr zainicjalizowany na podstawie sPtr. Następnie wypisz wynik logiczny zwrócony przez wPtr.expired() za pomocą std::cout.

Ładowanie edytora...
Pokaż wskazówkę

Zadeklaruj wskaźnik `weak_ptr` określając ten sam typ ogólny `<int>` i przypisz do niego bezpośrednio `sPtr`.

Rozwiązanie dostępne po 3 próbach

Ćwiczenie#cpp.m7.l2.e2
Próby: 0Ładowanie...

Użyj metody lock() na wPtr, aby uzyskać tymczasowy shared_ptr. Jeśli operacja powiedzie się (wskaźnik nie jest pusty), wypisz na ekranie wyłuskaną wartość.

Ładowanie edytora...
Pokaż wskazówkę

Zainicjalizuj zmienną wewnątrz bloku `if` wywołując `wPtr.lock()`, a następnie wypisz zasób wyłuskując go za pomocą gwiazdki `*`.

Rozwiązanie dostępne po 3 próbach