Last Updated: January 3, 2026
weak_ptr plays a crucial role in preventing circular references, which can lead to memory leaks.
In this chapter, we'll unpack what weak_ptr is, how it complements shared_ptr, and delve into practical scenarios where it shines.
Let’s get started!
weak_ptr?At its core, a weak_ptr is a smart pointer that holds a non-owning reference to an object managed by a shared_ptr. This means that the weak_ptr does not contribute to the reference count of the shared object. Consequently, it can observe an object without extending its lifetime.
This characteristic is particularly useful when you want to avoid circular references, which can happen in graphs or trees where two objects reference each other using shared_ptr.
Here's a simple illustration:
In the above example, both nodeA and nodeB will remain allocated indefinitely. Now, let’s see how we can avoid this using weak_ptr.
weak_ptrTo use weak_ptr, you typically create it from a shared_ptr. The syntax is straightforward:
When you want to access the object that a weak_ptr points to, you must convert it to a shared_ptr using the lock() method, which returns a shared_ptr. If the object has already been deallocated, lock() will return a null shared_ptr.
Here’s a practical example to illustrate this:
In this example, once res is reset, the weak_ptr no longer points to a valid object, and the call to lock() fails.
Circular references often arise in data structures like graphs and trees. Let’s consider a scenario where two nodes reference each other.
In this code, we use a weak_ptr for weakNeighbor. This ensures that nodeB does not keep nodeA alive, allowing both to be deleted when they go out of scope.
weak_ptrweak_ptr is not just a theoretical concept; it has several real-world applications. Let's explore a few:
Imagine a caching system where you want to keep references to objects but don’t want to prevent them from being deleted when they’re no longer needed. Using weak_ptr allows your cache to hold references without controlling the lifetime:
In this example, we can see a cache that doesn’t prevent its entries from being deleted when they are no longer in use.
When implementing the Observer design pattern, weak_ptr can be useful to avoid strong ownership of observers. This way, when the subject is destroyed, observers can be removed safely without causing memory leaks.
This pattern ensures that when an observer is out of scope, it won’t lead to dangling pointers or memory leaks.
While weak_ptr is powerful, it can lead to some confusion. Let’s clarify a few common misconceptions:
weak_ptr is Not a Replacement for shared_ptrRemember, weak_ptr does not manage the lifetime of the object. It’s only a way to observe. You still need a shared_ptr to own the object.
weak_ptr Can Still Outlive shared_ptrA weak_ptr can exist even when all shared_ptrs managing the object are destroyed. However, if you try to use it without checking if it’s valid, you'll run into problems.
Using the lock() function is essential. It’s your responsibility to check if the weak_ptr is still valid before using it. Failing to do this could lead to accessing a null pointer.