A pair of hands exchanging a key. Photo · Jacob Elliott / Unsplash
Ownership in C++: who holds the key now? The smart-pointer types make that question answerable, mechanically.

Heap memory is the great unsolved problem of C. malloc and free, paired by hand, leaking when forgotten, double-freed when over-zealous. The whole reason garbage collection exists — Java, Python, Go — is to take that pairing off the programmer's plate at the cost of a runtime overseer.

C++ has a different answer. Three small RAII wrappers in <memory>, each with a clear ownership rule. Use them, and your heap leaks vanish at compile time, not runtime. The chef pays nothing extra.

std::unique_ptr — exclusive ownership

"Exactly one place owns this object." When the unique_ptr goes out of scope, it deletes what it points at. You can move ownership to another unique_ptr, but you cannot copy it.

std::unique_ptr<Account> a = std::make_unique<Account>(42);
a->deposit(100);      // use it like a pointer
// ... at end of scope, the Account is automatically deleted

std::unique_ptr<Account> b = a;           // COMPILE ERROR: not copyable
std::unique_ptr<Account> b = std::move(a); // OK — ownership transferred to b; a is now empty

The compiler enforces single ownership. Trying to copy a unique_ptr fails to compile. Trying to use it after moving from it gives you a null pointer (and a tool warning). Cleaner than C, no overhead beyond a single pointer's worth of storage.

Use this 90% of the time. If you're not sure which smart pointer you need, start with unique_ptr.

std::shared_ptr — reference-counted shared ownership

"Several places might own this; delete it when the last one lets go."

std::shared_ptr<Tensor> x = std::make_shared<Tensor>(1024);
std::shared_ptr<Tensor> y = x;             // reference count: 2
// when both x and y go out of scope, count → 0, Tensor deleted

shared_ptr carries a reference count next to the object. Copies bump it; destructions decrement it. When the count hits zero, the object is freed.

It's not free: there's the cost of an atomic increment/decrement on every copy/destroy, plus the extra word for the count. For most code that's invisible. For high-throughput inner loops it shows up. Don't use shared_ptr by default; use it when ownership genuinely is shared. Lots of C++ codebases overuse it.

std::weak_ptr — observe without owning

If A owns B and B has a back-pointer to A, two shared_ptrs pointing at each other will never reach refcount zero — a cycle, and the equivalent of a leak. weak_ptr breaks the cycle: it observes a shared_ptr's object without contributing to its refcount.

Don't worry about weak_ptr until you have a cycle problem; you'll know.

The "no raw new" rule

Modern style: your code should never contain a raw new or delete. Every new hides immediately inside a make_unique or make_shared. Every heap allocation is owned by a smart pointer from the moment it exists. The class destructor handles the rest. The compiler enforces it.

The benefit isn't theoretical. The "use after free" / "double free" / "memory leak" bug categories — the ones responsible for half of every CVE filed against a C codebase — collectively become much harder to write in this style. They don't quite vanish (you can still misuse weak_ptr), but they get a great deal rarer.

Why this matters for AI

Tensors in PyTorch are reference counted. at::Tensor is a shared_ptr-like handle to a TensorImpl. When Python copies a tensor variable, the C++ side bumps the refcount. When the last reference drops, the underlying GPU memory returns to the pool. The pattern scales — you can have a tensor referenced from twenty places without anyone tracking lifetimes by hand.

Same in TensorFlow's core, in ONNX Runtime, in JAX's XLA. Smart pointers are the load-bearing memory abstraction for every modern AI framework written in C++.

The keyword delete belongs in your past. Smart pointers belong in your future.

Try it yourself

What's next

You've got the language. Time to meet the library that ships with it — and that almost every C++ project in existence depends on.

Week 26 is The STL — the Standard Template Library, with vectors, maps, sets, sorting, and the algorithms that come for free.

Photo credit

Photo free under the Unsplash license. Keys · Jacob Elliott.