Module lessons (2/2)
std::weak_ptr
Although std::shared_ptr is extremely useful, relying solely on shared ownership can lead to a problem known as a circular reference (or cyclic dependency).
If two or more objects each contain a shared_ptr pointing to the other, a closed loop is created. In this situation, the reference count of neither object will ever reach zero, preventing deallocation and causing a memory leak.
What is std::weak_ptr
To break ownership cycles, the standard library offers std::weak_ptr. This is a smart pointer that observes an object managed by a shared_ptr, but without incrementing the reference count.
It does not own the resource directly, so it does not prevent its destruction.
#include <memory>
std::shared_ptr<int> shared = std::make_shared<int>(42);
std::weak_ptr<int> weak = shared; // Does not increment reference count!
Verifying and Accessing the Resource
Because a weak_ptr does not own the resource, the resource could be deallocated at any time (when all associated shared_ptr instances go out of scope).
To use the observed resource, we must:
- Check if it is still valid using
expired(). - Temporarily convert the
weak_ptrinto ashared_ptrusing thelock()method. If the resource is still active,lock()returns a validshared_ptr, otherwise it returns a null pointer (nullptr).
if (!weak.expired()) {
// lock() creates a temporary shared_ptr to ensure safe access
if (std::shared_ptr<int> sharedAccess = weak.lock()) {
std::cout << *sharedAccess << std::endl;
}
} else {
std::cout << "Resource deallocated!" << std::endl;
}
Try it yourself
Declare a std::weak_ptr<int> named wPtr initialized from sPtr. Then print the boolean result returned by wPtr.expired() using std::cout.
Show hint
Declare the `weak_ptr` indicating the same generic type `<int>` and assign `sPtr` directly to it.
Solution available after 3 attempts
Use the lock() method on wPtr to obtain a temporary shared_ptr. If the operation succeeds (the pointer is not null), print the dereferenced value.
Show hint
Initialize a variable inside an `if` block by calling `wPtr.lock()`, then print the resource dereferencing it with the asterisk `*`.
Solution available after 3 attempts