Weak pointer

weak_ptr is a smart pointer provided by the C++ Standard Library in the header. It is used in conjunction with shared_ptr to prevent circular references, which can lead to memory leaks. Unlike shared_ptr, weak_ptr does not own the object it points to and does not affect the reference count. Instead, it provides a way to access an object managed by shared_ptr without increasing its reference count.

Code Example


Explanation

LeakNode Class
class 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;
  }
};

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;
  }
};
Creating Shared Pointers:
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

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;
Example of Good Memory Handling via weak_ptr
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;

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.