Leçons du module (2/2)
std::weak_ptr
Bien que std::shared_ptr soit extrêmement utile, l'utilisation exclusive de la propriété partagée peut entraîner un problème connu sous le nom de référence cyclique (ou cyclic dependency).
Si deux objets ou plus contiennent chacun un shared_ptr qui pointe vers l'autre, un cycle fermé se crée. Dans cette situation, le compteur de références d'aucun des deux objets ne descendra jamais à zéro, empêchant la désallocation et provoquant une fuite de mémoire (memory leak).
Qu'est-ce que std::weak_ptr ?
Pour casser les cycles de propriété, la bibliothèque standard propose std::weak_ptr. Il s'agit d'un pointeur intelligent qui observe un objet géré par un shared_ptr, mais sans incrémenter le reference count.
Il ne possède pas directement la ressource, il n'empêche donc pas sa destruction.
#include <memory>
std::shared_ptr<int> shared = std::make_shared<int>(42);
std::weak_ptr<int> weak = shared; // Non incrementa il contatore!
Vérifier et accéder à la ressource
Comme un weak_ptr ne possède pas la ressource, celle-ci peut être désallouée à tout moment (lorsque tous les shared_ptr associés sortent de la portée).
Pour utiliser la ressource observée, nous devons d'abord :
- Vérifier si elle est toujours valide à l'aide de
expired(). - Convertir temporairement le
weak_ptren unshared_ptrvia la méthodelock(). Si la ressource est toujours active,lock()renvoie unshared_ptrvalide, sinon elle renvoie un pointeur nul (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;
}
À vous de jouer
Déclarez un std::weak_ptr<int> nommé wPtr initialisé à partir de sPtr. Affichez ensuite le résultat booléen renvoyé par wPtr.expired() à l'aide de std::cout.
Afficher l'indice
Déclarez le `weak_ptr` en indiquant le même type générique `<int>` et affectez-lui directement `sPtr`.
Solution disponible après 3 tentatives
Utilisez la méthode lock() sur wPtr pour obtenir un shared_ptr temporaire. Si l'opération réussit (le pointeur n'est pas nul), affichez à l'écran la valeur déréférencée.
Afficher l'indice
Initialisez une variable à l'intérieur d'un bloc `if` en appelant `wPtr.lock()`, puis affichez la ressource en la déréférençant avec l'astérisque `*`.
Solution disponible après 3 tentatives