Weak pointer
weak_ptr is a smart pointer provided by the C++ Standard Library in the
Code Example
Explanation
LeakNode Classclass LeakNode { // a bad example which has memory leakage
public:
string name;
shared_ptr<LeakNode> next;
LeakNode(string name) : name(name) {
cout << name << " constructor" << endl;
}
~LeakNode() {
cout << name << " destructor" << endl;
}
};
- The LeakNode class has a name and a shared_ptr to the next LeakNode.
- It demonstrates a scenario where circular references can lead to memory leaks because shared_ptr objects refer to each other.
GoodNode Class
class GoodNode { // a good example that weak_ptr resolves the memory leakage
public:
string name;
weak_ptr<GoodNode> next;
GoodNode(string name) : name(name) {
cout << name << " constructor" << endl;
}
~GoodNode() {
cout << name << " destructor" << endl;
}
};
- The GoodNode class has a name and a weak_ptr to the next GoodNode.
- Using weak_ptr prevents circular references and thus avoids memory leaks.
shared_ptr<MyClass> ptr1 = make_shared<MyClass>();
cout << ptr1.use_count() << " pointer to the object" << endl;
shared_ptr<MyClass> ptr2 = ptr1;
cout << ptr1.use_count() << " pointers to the object" << endl;
weak_ptr<MyClass> ptr3 = ptr1;
cout << ptr1.use_count() << " pointers to the object" << endl; // weak_ptr doesn't increase use_count
- We create a shared_ptr named ptr1 that manages a new MyClass object.
- We create another shared_ptr named ptr2 that shares ownership of the same object as ptr1.
- The use_count function shows that there are two shared_ptr instances pointing to the same object.
- We create a weak_ptr named ptr3 that observes ptr1 without increasing the reference count.
Example of Memory Leakage
shared_ptr<LeakNode> leak1 = make_shared<LeakNode>("leak node1");
shared_ptr<LeakNode> leak2 = make_shared<LeakNode>("leak node2");
// the following creates a circle, use_count will never reach 0 hence memory will not be called
leak1->next = leak2;
leak2->next = leak1;
- We create two LeakNode instances (leak1 and leak2) managed by shared_ptr.
- Creating circular references (leak1 -> leak2 and leak2 -> leak1) results in a memory leak because the reference count will never reach zero.
shared_ptr<GoodNode> good1 = make_shared<GoodNode>("good node1");
shared_ptr<GoodNode> good2 = make_shared<GoodNode>("good node2");
// weak_ptr won't create a circle
good1->next = good2;
good2->next = good1;
- We create two GoodNode instances (good1 and good2) managed by shared_ptr.
- Using weak_ptr to reference each other prevents circular references and thus avoids memory leaks.
Conclusion
weak_ptr is an essential tool in C++ for managing dynamic memory safely. It prevents circular references by observing objects managed by shared_ptr without increasing their reference count. This helps ensure that memory is properly released when it is no longer needed, avoiding potential memory leaks.