Sobes.tech
Middle

What is the difference between weak_ptr and shared_ptr?

sobes.tech AI

Answer from AI

The main difference lies in managing the object's lifetime.

shared_ptr manages the resource using a reference count of strong references. The object is destroyed when the last shared_ptr pointing to it ceases to exist (the strong reference count becomes zero). shared_ptr increments this count upon copying.

weak_ptr does not claim ownership of the object. It holds a "weak" reference to the resource managed by shared_ptr and does not increase the strong reference count. weak_ptr does not prevent the object from being destroyed. Its main purpose is to access the object if it still exists, without participating in managing its lifetime.

To access the object pointed to by weak_ptr, it must be converted to shared_ptr using the lock() method. This method returns a shared_ptr if the object is still alive, or an empty shared_ptr otherwise.

Examples of usage:

  1. Preventing cyclic references: shared_ptr can create cyclic references, leading to memory leaks. weak_ptr is used to break such cycles.
  2. Observers: Observer objects often hold weak_ptr to the observed object to avoid artificially prolonging its lifetime.
  3. Caches: Caches may store weak_ptr to objects so they can be unloaded by garbage collection (if applicable) or simply destroyed if there are no other strong references to them.

Summary table:

Feature shared_ptr weak_ptr
Resource management Yes (strong reference) No (weak reference)
Strong reference count Increases Does not increase
Prevents destruction Yes No
Direct access to object Yes (->, *) No (only via lock())
Usage in cyclic references Leads to leaks Used to break them

Example with cyclic references:

#include <iostream>
#include <memory>

class B;

class A {
public:
    std::shared_ptr<B> b_ptr;
    ~A() { std::cout << "A Destructor\n"; }
};

class B {
public:
    std::weak_ptr<A> a_ptr; // Using weak_ptr to break the cycle
    ~B() { std::cout << "B Destructor\n"; }
};

int main() {
    std::shared_ptr<A> a = std::make_shared<A>();
    std::shared_ptr<B> b = std::make_shared<B>();

    a->b_ptr = b;
    b->a_ptr = a; // Here weak_ptr is used

    // When main ends, a and b will be destroyed,
    // as there are no cyclic references holding them.

    return 0;
}