std::weak_ptr โ€” Non-Owning Observer

๐Ÿง  Concept

A std::weak_ptr is a non-owning smart pointer that observes an object managed by a std::shared_ptr. It does not affect the reference count, meaning it does not extend the objectโ€™s lifetime.

It is mainly used to break cyclic dependencies (e.g., two shared_ptrs referencing each other, creating a memory leak because neither gets destroyed).

๐Ÿงท Key Features:


โœ… Basic Syntax and Usage

#include <iostream>
#include <memory>

class Resource {
public:
    Resource(int id) : id_(id) { std::cout << "Resource " << id_ << " acquired.\\n"; }
    ~Resource() { std::cout << "Resource " << id_ << " released.\\n"; }
    void show() const { std::cout << "Resource ID: " << id_ << "\\n"; }
private:
    int id_;
};

int main() {
    std::shared_ptr<Resource> sp = std::make_shared<Resource>(100);

    std::weak_ptr<Resource> wp = sp;  // Create weak_ptr from shared_ptr
    std::cout << "Use count (shared): " << sp.use_count() << "\\n";  // โ†’ 1

    if (!wp.expired()) {
        std::shared_ptr<Resource> sp2 = wp.lock();  // Convert to shared_ptr
        if (sp2) {
            sp2->show();  // Safe to use
            std::cout << "Use count (shared): " << sp.use_count() << "\\n";  // โ†’ 2
        }
    }

    sp.reset();  // Destroy the managed object
    if (wp.expired()) {
        std::cout << "Resource has expired.\\n";
    }

    return 0;
}

๐Ÿ”„ Use Case:

Breaking Cyclic References

#include <iostream>
#include <memory>

struct B;  // Forward declaration

struct A {
    std::shared_ptr<B> b_ptr;
    ~A() { std::cout << "A destroyed\\n"; }
};

struct B {
    std::weak_ptr<A> a_ptr;  // weak_ptr avoids cycle
    ~B() { std::cout << "B destroyed\\n"; }
};

int main() {
    auto a = std::make_shared<A>();
    auto b = std::make_shared<B>();
    a->b_ptr = b;
    b->a_ptr = a;  // weak_ptr avoids cyclic dependency

    return 0;
}

If B::a_ptr were a shared_ptr, both a and b would never be destroyed due to the cyclic reference.


๐Ÿ› ๏ธ Member Functions