weak_ptr in C++

Last Updated : 14 Jul, 2026

A std::weak_ptr is a smart pointer introduced in C++11 that provides a non-owning reference to an object managed by a std::shared_ptr. Unlike shared_ptr, it does not contribute to the reference count, making it useful for observing objects without extending their lifetime.

  • Observes objects without affecting their ownership or lifetime.
  • Safely checks whether the managed object still exists before accessing it.

Example: Creating and Using a weak_ptr

C++
#include <iostream>
#include <memory>
using namespace std;

int main() {

    shared_ptr<int> sp = make_shared<int>(50);

    weak_ptr<int> wp = sp;

    if (auto ptr = wp.lock()) {
        cout << *ptr << endl;
    }

    return 0;
}

Output
50

Explanation

  • sp owns the dynamically allocated integer.
  • wp observes the same object without increasing its reference count.
  • lock() creates a temporary shared_ptr only if the object still exists

Syntax

std::weak_ptr<Type> ptr;

where Type is the type of the managed object.

Common Member Functions

The following are some member functions associated with std::weak_ptr to provide different functionalities.

FunctionDescription
lock()Returns a shared_ptr if the object still exists; otherwise returns an empty shared_ptr.
expired()Returns true if the managed object has already been destroyed.
use_count()Returns the number of shared_ptrs owning the object.
reset()Releases the reference held by the weak_ptr.
swap()Exchanges the contents of two weak_ptrs.
owner_before()Compares ownership with another smart pointer.

Preventing Circular References

The following example demonstrates how std::weak_ptr breaks circular references while allowing the managed objects to be destroyed correctly.

C++
#include <iostream>
#include <memory>
using namespace std;

class B;

class A {
public:
    shared_ptr<B> ptrB;
    ~A() {
        cout << "A destroyed\n";
    }
};

class B {
public:
    weak_ptr<A> ptrA;

    ~B() {
        cout << "B destroyed\n";
    }
};

int main() {

    auto a = make_shared<A>();
    auto b = make_shared<B>();

    a->ptrB = b;
    b->ptrA = a;

    return 0;
}

Output
A destroyed
B destroyed

Explanation: If ptrA were a shared_ptr, both objects would keep each other alive and neither destructor would execute. Using weak_ptr breaks the ownership cycle, allowing both objects to be destroyed correctly.

Advantages of weak_ptr

The following are the major advantages of using std::weak_ptr in C++

  • Prevents circular references between shared_ptr objects.
  • Does not increase the reference count of the managed object.
  • Allows safely checking whether an object still exists before accessing it.
  • Works seamlessly with shared_ptr through the lock() function.

Best Practices

Follow these best practices to use std::weak_ptr safely and effectively in C++:

  • Use weak_ptr whenever an object needs to observe another object without owning it.
  • Always verify the result of lock() before accessing the managed object.
  • Prefer weak_ptr over raw pointers when observing objects managed by shared_ptr.
  • Use it to break circular references in object graphs.

Applications of weak_ptr

The following are some common scenarios where std::weak_ptr is widely used:

  • Breaking circular references between objects that use std::shared_ptr, preventing memory leaks.
  • Implementing observer patterns where objects need to monitor others without taking ownership.
  • Building cache systems that temporarily reference objects without extending their lifetime.
  • Managing graphs, trees, and bidirectional relationships where cyclic references are common.
Comment