Lezioni del modulo (2/2)
std::weak_ptr
Sebbene std::shared_ptr sia estremamente utile, l'uso esclusivo di proprietà condivisa può portare ad un problema noto come riferimento ciclico (o cyclic dependency).
Se due o più oggetti contengono ciascuno uno shared_ptr che punta all'altro, si crea un ciclo chiuso. In questa situazione, il contatore dei riferimenti di nessuno dei due oggetti scenderà mai a zero, impedendo la deallocazione ed originando un memory leak.
Cos'è std::weak_ptr
Per rompere i cicli di proprietà, la libreria standard offre std::weak_ptr. Si tratta di un puntatore intelligente che osserva un oggetto gestito da uno shared_ptr, ma senza incrementare il reference count.
Non possiede direttamente la risorsa, quindi non impedisce la sua distruzione.
#include <memory>
std::shared_ptr<int> shared = std::make_shared<int>(42);
std::weak_ptr<int> weak = shared; // Non incrementa il contatore!
Verificare e Accedere alla Risorsa
Poiché un weak_ptr non possiede la risorsa, questa potrebbe essere deallocata in qualsiasi momento (quando tutti gli shared_ptr associati vanno fuori scope).
Per utilizzare la risorsa osservata, dobbiamo prima:
- Controllare se è ancora valida usando
expired(). - Convertire temporaneamente il
weak_ptrin unoshared_ptrtramite il metodolock(). Se la risorsa è ancora attiva,lock()restituisce unoshared_ptrvalido, altrimenti restituisce un puntatore nullo (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;
}
Prova tu
Dichiara un std::weak_ptr<int> chiamato wPtr inizializzato a partire da sPtr. Dopodiché stampa il risultato booleano restituito da wPtr.expired() usando std::cout.
Mostra suggerimento
Dichiara il `weak_ptr` indicando lo stesso tipo generico `<int>` ed assegna direttamente `sPtr` ad esso.
Soluzione disponibile dopo 3 tentativi
Usa il metodo lock() su wPtr per ottenere uno shared_ptr temporaneo. Se l'operazione ha successo (il puntatore non è nullo), stampa a schermo il valore dereferenziato.
Mostra suggerimento
Inizializza una variabile dentro un blocco `if` richiamando `wPtr.lock()`, poi stampa la risorsa dereferenziandola con l'asterisco `*`.
Soluzione disponibile dopo 3 tentativi