Lecciones del módulo (2/2)
std::weak_ptr
Aunque std::shared_ptr es extremadamente útil, el uso exclusivo de la propiedad compartida puede provocar un problema conocido como referencia cíclica (o cyclic dependency).
Si dos o más objetos contienen cada uno un shared_ptr que apunta al otro, se crea un ciclo cerrado. En esta situación, el contador de referencias de ninguno de los dos objetos llegará a cero, lo que impide la liberación de memoria y genera una fuga de memoria (memory leak).
¿Qué es std::weak_ptr?
Para romper los ciclos de propiedad, la biblioteca estándar ofrece std::weak_ptr. Se trata de un puntero inteligente que observa un objeto gestionado por un shared_ptr, pero sin incrementar el reference count.
No posee directamente el recurso, por lo que no impide su destrucción.
#include <memory>
std::shared_ptr<int> shared = std::make_shared<int>(42);
std::weak_ptr<int> weak = shared; // Non incrementa il contatore!
Verificar y Acceder al Recurso
Dado que un weak_ptr no posee el recurso, este podría liberarse en cualquier momento (cuando todos los shared_ptr asociados salen del ámbito).
Para utilizar el recurso observado, primero debemos:
- Comprobar si todavía es válido usando
expired(). - Convertir temporalmente el
weak_ptren unshared_ptrmediante el métodolock(). Si el recurso sigue activo,lock()devuelve unshared_ptrválido; de lo contrario, devuelve un puntero nulo (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;
}
Pruébalo tú mismo
Declara un std::weak_ptr<int> llamado wPtr inicializado a partir de sPtr. Después imprime el resultado booleano devuelto por wPtr.expired() usando std::cout.
Mostrar pista
Declara el `weak_ptr` indicando el mismo tipo genérico `<int>` y asígnale directamente `sPtr`.
Solución disponible después de 3 intentos
Usa el método lock() en wPtr para obtener un shared_ptr temporal. Si la operación tiene éxito (el puntero no es nulo), imprime en pantalla el valor dereferenciado.
Mostrar pista
Inicializa una variable dentro de un bloque `if` llamando a `wPtr.lock()`, luego imprime el recurso dereferenciándolo con el asterisco `*`.
Solución disponible después de 3 intentos