AlgoMaster Logo

weak ptr

Last Updated: January 3, 2026

6 min read

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!

What is 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.

How to Use weak_ptr

To 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 and Their Resolution

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.

Practical Applications of weak_ptr

weak_ptr is not just a theoretical concept; it has several real-world applications. Let's explore a few:

1. Caching Mechanisms

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.

2. Observer Patterns

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.

Common Misconceptions

While weak_ptr is powerful, it can lead to some confusion. Let’s clarify a few common misconceptions:

1. weak_ptr is Not a Replacement for shared_ptr

Remember, 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.

2. weak_ptr Can Still Outlive shared_ptr

A 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.

3. Locking Mechanism

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.