C++ Weak Pointer
A `weak_ptr` in C++ is a smart pointer that holds a non-owning reference to an object managed by `shared_ptr`. It does not affect the reference count, preventing circular references that could lead to memory leaks. `weak_ptr` must be converted to `shared_ptr` to access the object safely.
1. What is a Weak Pointer?
A `weak_ptr` is a smart pointer that refers to an object managed by `shared_ptr` but does not contribute to its reference count. It is mainly used to break circular references and observe objects without owning them.
#include <iostream>
#include <memory>
using namespace std;
int main() {
shared_ptr<int> sp = make_shared<int>(42);
weak_ptr<int> wp = sp; // weak_ptr observes sp
cout << "Reference count: " << sp.use_count() << endl; // 1
if (auto temp = wp.lock()) { // Convert weak_ptr to shared_ptr
cout << "Value: " << *temp << endl;
} else {
cout << "Object expired" << endl;
}
sp.reset(); // Delete managed object
if (auto temp = wp.lock()) {
cout << "Value: " << *temp << endl;
} else {
cout << "Object expired" << endl;
}
return 0;
}
2. Advantages of weak_ptr
1. **Prevents Circular References:** Does not increase reference count. 2. **Observes Objects Safely:** Can check if the object still exists. 3. **Memory Safety:** Avoids dangling references by locking weak_ptr before access. 4. **Works with shared_ptr:** Ideal companion for shared ownership scenarios.
3. Example of Breaking Circular References
#include <iostream>
#include <memory>
using namespace std;
struct Node {
int value;
shared_ptr<Node> next;
weak_ptr<Node> prev; // Use weak_ptr to prevent cycle
Node(int val) : value(val) {}
};
int main() {
shared_ptr<Node> node1 = make_shared<Node>(1);
shared_ptr<Node> node2 = make_shared<Node>(2);
node1->next = node2;
node2->prev = node1; // weak_ptr breaks cycle
cout << "node2 prev points to node1: " << node2->prev.lock()->value << endl;
return 0;
}
4. Things to Be Careful About
1. Cannot directly dereference weak_ptr; must lock first. 2. Accessing object after it expires returns null. 3. Avoid holding weak_ptr longer than necessary without locking. 4. Not suitable for exclusive ownership scenarios.
5. Best Practices
1. Use weak_ptr to break circular references in shared_ptr graphs. 2. Always check `lock()` return value before using the object. 3. Prefer weak_ptr for observer patterns where ownership is not needed. 4. Combine with shared_ptr carefully to avoid dangling references. 5. Keep weak_ptr usage minimal to maintain code clarity.
Conclusion
`weak_ptr` is a non-owning smart pointer that complements shared_ptr by preventing circular references and allowing safe observation of objects. Proper use of weak_ptr ensures memory safety, avoids leaks, and allows efficient memory management in modern C++ applications.
Codecrown