Skip to content
Free public beta until December 4, 2026: every course is open, no card needed. After that, the first chapter of each course stays free and full access is a one-time $39 ($19 for up to 100 founding members chosen for helpful feedback). Your progress is kept. How the beta works

Every way to own memory

Plain values, containers, unique_ptr, shared_ptr, weak_ptr and borrowing. Who ends each object's life, and how to choose.

Every object needs an answer to one question: who is responsible for ending its life? Work down this list and stop at the first answer that fits.

  1. A plain value, or a container of values (Contact c;, std::vector<Contact>). No heap code of your own. This is the default, and it covers most programs.
  2. std::unique_ptr: one owner, when a plain value won't do. The object may be absent, must outlive a scope, or is one of several related types.
  3. std::shared_ptr: only when ownership is truly shared and you can't say in advance which owner finishes last.
  4. std::weak_ptr: to watch a shared object without keeping it alive (caches, back links, breaking a cycle).
  5. A reference or a raw pointer: to use something someone else owns. Borrowers never delete.

Raw new/delete and C's malloc/free aren't on the list. They belong inside the implementation of tools like these, and you should recognize them in older code.

Owned for you

A local lives until its block ends, and is destroyed in reverse order. No code needed.

std::vector, std::string and the other containers allocate and free their own heap memory.

A constructor acquires, the destructor releases, and the scope decides when.

Smart pointers

Can be moved but never copied. The same size as a raw pointer, and no extra cost at run time.

Shared ownership through a reference count, and the choosing-an-owner list above.

Classes that own things

Build a class from members that own themselves and it needs no destructor, copy or move code.

The rare class that owns a raw resource writes all five special members.

The Old Way, to recognize

Every new needs exactly one matching delete, and nothing may use the object afterwards. The compiler doesn't check it.