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:
- Preventing cyclic references:
shared_ptrcan create cyclic references, leading to memory leaks.weak_ptris used to break such cycles. - Observers: Observer objects often hold
weak_ptrto the observed object to avoid artificially prolonging its lifetime. - Caches: Caches may store
weak_ptrto 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;
}