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 forshared_ptronly when ownership is genuinely shared. - Create with
make_unique/make_shared: exception-safe and (for shared) one allocation. - Use
weak_ptrfor 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.