cs.thefarshad
medium

Smart Pointers

Let ownership manage memory — unique_ptr, shared_ptr, and weak_ptr free resources automatically with RAII.

Raw new and delete force you to track ownership by hand, which leaks memory the moment an early return or exception skips the delete. Smart pointers from the <memory> header fix this by tying ownership to RAII: when the owning pointer goes out of scope, the managed object is freed for you.

std::shared_ptr allows several owners and keeps a reference count of how many exist. The object lives until that count hits zero. A std::weak_ptr can observe the object without owning it, so it never bumps the count. Step through the program below to watch the count rise on copy, fall at scope exit, and drop to zero on reset — freeing the object automatically.

> auto a = std::make_shared<Widget>(); // count = 1
{
auto b = a; // copy -> shared
std::weak_ptr<Widget> w = a; // observes only
} // b destroyed here
a.reset(); // release last owner
Pointers in scope
ashared_ptr→ Widget
bshared_ptrout of scope
wweak_ptrout of scope
strong count
1
Widget (alive)
1/6
shared (owns)weak (observes)make_shared allocates the Widget and a control block. a is the sole owner, so the strong count is 1.

unique_ptr: one exclusive owner

std::unique_ptr owns its object alone. It cannot be copied — only moved — so ownership is always unambiguous. It is the default choice and has zero overhead versus a raw pointer.

#include <memory>

auto p = std::make_unique<Widget>();   // p is the sole owner
use(*p);
// auto q = p;            // ERROR: cannot copy a unique_ptr
auto q = std::move(p);    // OK: ownership transfers; p is now null
// q's Widget is deleted automatically when q goes out of scope

shared_ptr and weak_ptr: shared ownership

std::shared_ptr reference-counts the object across many owners. Use weak_ptr to break ownership cycles — for example, a child that needs to reach back to its parent without keeping it alive.

auto a = std::make_shared<Widget>();   // count = 1
{
  auto b = a;     // copy -> count = 2 (shared ownership)
  use(*b);
}                   // b destroyed -> count = 1
a.reset();          // count = 0 -> Widget deleted here

The cycle caveat

Reference counting cannot reclaim a cycle. If object A holds a shared_ptr to B and B holds one back to A, each keeps the other’s count at one forever, so neither is ever freed — a leak. The fix is to make one of the two links a weak_ptr, which observes without contributing to the count. Reach for raw new and delete essentially never in modern C++.

Takeaways

  • Smart pointers tie ownership to scope, so memory is freed automatically (RAII), even on exceptions.
  • unique_ptr is one exclusive owner (move-only); prefer it by default.
  • shared_ptr reference-counts shared ownership; the object dies when the count reaches zero.
  • weak_ptr observes without owning — use it to break reference cycles that would otherwise leak.
  • Build them with make_unique / make_shared; avoid raw new and delete.