Article by Ayman Alheraki on January 11 2026 10:36 AM
std::weak_ptr in C++std::weak_ptr is one of the smart pointer types in the STL (Standard Template Library). It is used to solve the problem of cyclic references, which can lead to memory leaks when using std::shared_ptr.
In this article, we will explain the best way to use std::weak_ptr, the appropriate scenarios for its use, along with clear examples.
std::weak_ptr?std::weak_ptr does not share ownership of the object it points to with std::shared_ptr. Instead:
It acts as a weak reference to the object managed by std::shared_ptr, without affecting its reference count.
It prevents memory leaks in cases of cyclic references.
std::weak_ptr?When two or more objects refer to each other using std::shared_ptr, their reference counts never drop to zero, resulting in memory leaks.
std::weak_ptrBy using std::weak_ptr, the reference count of the managed object is not increased.
You can check if the managed object is still valid using expired().
To access the object, you can convert the std::weak_ptr to std::shared_ptr using lock().
std::weak_ptrWhen There Are Cyclic References:
If two (or more) objects are connected and use std::shared_ptr, you should use std::weak_ptr to break the cycle.
To Reference an Object Without Affecting Its Lifetime:
Use std::weak_ptr when you need a temporary reference to an object managed by std::shared_ptr.
For Complex Data Structures: Such as trees or graphs, where nodes are interconnected.
xxxxxxxxxx
struct Node { std::shared_ptr<Node> next; // Points to the next node std::weak_ptr<Node> prev; // Points to the previous node ~Node() { std::cout << "Node destroyed\n"; }};
int main() { auto node1 = std::make_shared<Node>(); auto node2 = std::make_shared<Node>();
node1->next = node2; // node1 points to node2 node2->prev = node1; // node2 points to node1 using weak_ptr
return 0; // No memory leak occurs due to the use of weak_ptr}lock()
void checkNode(const std::weak_ptr<int>& weakPtr) { if (auto sharedPtr = weakPtr.lock()) { std::cout << "Value: " << *sharedPtr << "\n"; } else { std::cout << "Pointer is expired\n"; }}
int main() { std::weak_ptr<int> weakPtr;
{ auto sharedPtr = std::make_shared<int>(42); weakPtr = sharedPtr;
checkNode(weakPtr); // Value: 42 } // sharedPtr is destroyed here
checkNode(weakPtr); // Pointer is expired return 0;}expired() to Check
void checkExpiration(const std::weak_ptr<int>& weakPtr) { if (weakPtr.expired()) { std::cout << "The weak pointer is expired.\n"; } else { std::cout << "The weak pointer is still valid.\n"; }}
int main() { auto sharedPtr = std::make_shared<int>(100); std::weak_ptr<int> weakPtr = sharedPtr;
checkExpiration(weakPtr); // The weak pointer is still valid.
sharedPtr.reset(); // The object is destroyed
checkExpiration(weakPtr); // The weak pointer is expired. return 0;}std::weak_ptr?If there is no risk of cyclic references.
If you need full control over the object’s lifetime (use std::shared_ptr or std::unique_ptr instead).
std::weak_ptr is a powerful tool in C++, used to solve cyclic reference issues and prevent memory leaks.
Use it when you need a weak reference to an object without affecting its reference count.
Always check whether the managed object is still valid using expired() or lock() before accessing it.
By using std::weak_ptr correctly, you can build more efficient and stable applications.