Reference · Memory

Smart pointers & RAII

Smart pointers tie an object’s lifetime to a scope, so memory frees itself. Here’s RAII, ownership, reference counting, and the cycle trap to avoid.

The idea: lifetime tied to scope (RAII)

Manual new/delete leaks whenever a delete is skipped, an early return, a thrown exception, an unclear owner. RAII, Resource Acquisition Is Initialization: fixes this by tying a resource to an object’s lifetime: acquire in the constructor, release in the destructor. When the object goes out of scope, the destructor runs automatically, even when an exception unwinds the stack. A smart pointer is RAII applied to heap memory, it owns a pointer and frees it for you.

unique_ptr, single ownership

std::unique_ptr models exactly one owner. It cannot be copied, only moved, so ownership transfers explicitly and there’s never ambiguity about who frees the memory. It has essentially zero overhead over a raw pointer. This is the default, reach for unique_ptr first and only upgrade if you genuinely need shared ownership.

shared_ptr, reference-counted ownership

std::shared_ptr lets several owners share an object. It keeps a reference count: each copy increments it, each destruction decrements it, and when the count hits zero the object is deleted. That convenience costs an atomic counter per copy and a heap control block, so use it only when ownership is truly shared, not as a lazy default.

The cycle trap, and weak_ptr

Reference counting has one classic failure: a cycle. If object A holds a shared_ptr to B and B holds one back to A, their counts never reach zero and neither is ever freed, a leak that reference counting alone can’t solve. The fix is std::weak_ptr: a non-owning reference that observes a shared_ptr without incrementing the count. Make the “back-pointer” in a parent/child or observer relationship a weak_ptr and the cycle breaks.

Rules of thumb

  • Prefer unique_ptr; reach for shared_ptr only when ownership is genuinely shared.
  • Create with make_unique / make_shared: exception-safe and (for shared) one allocation.
  • Use weak_ptr for back-references to break cycles.
  • Pass a raw pointer or reference when a function only uses an object without taking ownership.

FAQ

Do smart pointers exist outside C++?

The exact types are C++, but the idea, tying resource lifetime to scope (RAII), appears as using/try-with-resources in C#/Java and context managers in Python. Reference counting also underlies many garbage collectors.

Is shared_ptr thread-safe?

The reference count is atomic, so copying/destroying a shared_ptr across threads is safe. The object it points to is not automatically protected, you still need synchronization for that.

Can smart pointers still leak?

Yes, through reference cycles of shared_ptr. That’s exactly what weak_ptr is for.

Related

See memory leaks and C++ type casting, or the full Reference.