Smart Pointers in C++

Smart pointers are wrapper classes around raw pointers that automatically manage memory. They eliminate the need to manually call delete and prevent common memory bugs like memory leaks and dangling pointers. Introduced in C++11, smart pointers are defined in the <memory> header.

The Problem with Raw Pointers

int *p = new int(42);
// ... some code that might throw an exception ...
delete p;    // If exception occurs above, this is never reached!
             // Result: Memory leak

Smart pointers solve this by automatically releasing memory when they go out of scope — regardless of how the scope is exited.

Types of Smart Pointers

Smart PointerOwnershipUse Case
unique_ptrSingle ownerWhen only one owner is needed
shared_ptrMultiple owners (reference counted)When multiple parts need the same resource
weak_ptrNon-owning observerTo break circular references

unique_ptr — Exclusive Ownership

A unique_ptr is the sole owner of the memory it manages. When it goes out of scope, the memory is automatically freed. It cannot be copied — only moved.

#include <iostream>
#include <memory>
using namespace std;

int main() {
    unique_ptr<int> ptr = make_unique<int>(42);
    cout << "Value: " << *ptr << endl;

    // No need for delete — memory freed automatically
    return 0;
}

Output:

Value: 42

unique_ptr with a Class:

class Dog {
public:
    string name;
    Dog(string n) : name(n) { cout << name << " created.
"; }
    ~Dog() { cout << name << " destroyed.
"; }
    void bark() { cout << name << " says Woof!
"; }
};

int main() {
    {
        unique_ptr<Dog> d = make_unique<Dog>("Bruno");
        d->bark();
    }   // Bruno is automatically destroyed here
    cout << "After block." << endl;
    return 0;
}

Output:

Bruno created.
Bruno says Woof!
Bruno destroyed.
After block.

Transferring Ownership with move:

unique_ptr<int> p1 = make_unique<int>(10);
unique_ptr<int> p2 = move(p1);   // ownership transferred to p2
// p1 is now nullptr
cout << *p2 << endl;   // 10

shared_ptr — Shared Ownership

A shared_ptr allows multiple pointers to share ownership of the same object. It maintains a reference count — each time a new shared_ptr points to the object, the count increases. When the count reaches zero, the memory is freed.

#include <iostream>
#include <memory>
using namespace std;

int main() {
    shared_ptr<int> p1 = make_shared<int>(100);
    shared_ptr<int> p2 = p1;    // both share ownership

    cout << "Value: "     << *p1            << endl;
    cout << "Use count: " << p1.use_count() << endl;

    p2.reset();   // p2 releases ownership
    cout << "After reset, count: " << p1.use_count() << endl;

    return 0;
}

Output:

Value: 100
Use count: 2
After reset, count: 1

weak_ptr — Non-Owning Reference

A weak_ptr observes an object managed by shared_ptr without affecting the reference count. It is used to break circular references — a situation where two shared_ptrs point to each other, preventing cleanup.

shared_ptr<int> sp = make_shared<int>(42);
weak_ptr<int> wp = sp;

cout << "shared count: " << sp.use_count() << endl;   // 1 (wp doesn't count)

if (auto locked = wp.lock()) {   // convert to shared_ptr to use
    cout << "Value: " << *locked << endl;
}

Output:

shared count: 1
Value: 42

Smart Pointer vs Raw Pointer

FeatureRaw PointerSmart Pointer
Memory managementManual (delete required)Automatic
Memory leaksCommon if delete is missedPrevented automatically
Null safetyRiskySafer with checks
OverheadNoneSlight overhead (reference counting)

Best Practices

  • Prefer make_unique and make_shared over new — safer and more efficient.
  • Use unique_ptr by default — only use shared_ptr when shared ownership is truly needed.
  • Use weak_ptr to break cycles between shared_ptr objects.
  • Avoid using raw pointers for ownership — use smart pointers instead.

Key Takeaways

  • Smart pointers automatically free memory when they go out of scope.
  • unique_ptr — single owner; memory released when it goes out of scope.
  • shared_ptr — multiple owners; memory freed when last owner is gone.
  • weak_ptr — non-owning observer; used to avoid circular reference leaks.
  • Always prefer smart pointers over raw new/delete for safer memory management.

Leave a Comment

Your email address will not be published. Required fields are marked *