stack · main()heap (free store)unique_ptr aunique_ptr bshared_ptr sshared_ptr t0x5a10use count0x5a401#include <iostream>2#include <memory>3int main() {4 auto a = std::make_unique<int>(7);5 auto b = std::move(a);6 auto s = std::make_shared<int>(5);7 {8 auto t = s;9 std::cout << s.use_count() << '\n';10 }11 std::cout << s.use_count() << '\n';12}×make_unique0x5a10copy0x5a10make_shared0x5a400x5a40+12-11-1delete
Violet card: the program (owners.cpp); a highlighted line is the one runningBlue cells: the smart pointers on the stack; khaki cells: ints on the heap; sand: the use count (faint = gone)Arrows: what each smart pointer owns; dashed outline: the one block make_shared makesIn front: the source card owners.cpp and the output block. At the back: main's stack frame with the smart pointers a, b (unique_ptr) and s, t (shared_ptr), and the heap with the int 7 and, in one block, a control block (use count) and the int 5. An arrow shows what each smart pointer owns. A unique_ptr cannot be copied, only moved; a shared_ptr can be copied, and the use count says how many owners there are. When the last owner goes away, the object is deleted, so the program never writes delete and leaks nothing. The addresses 0x5a10, 0x5a30 and 0x5a40 are made up and short so they fit. Real ones are longer, change from run to run, and the layout of the control block is up to the library.

Owning

  1. With new and delete you must remember every delete yourself. A smart pointer is a small object on the stack that owns a heap object. When the smart pointer is destroyed, its destructor deletes what it owns. This is RAII.

One owner

Shared owners

Cleaning up

What happens

;; step 1/11 · owner
raw pointer:    int* p = new int(7);
                ... you must write delete p; on every path
smart pointer:  an object that OWNS the heap object
                its destructor deletes it for you
#include <memory>  gives std::unique_ptr, std::shared_ptr
RAII: a resource is tied to an object's lifetime

The addresses 0x5a10, 0x5a30 and 0x5a40 are made up and short so they fit. Real ones are longer, change from run to run, and the layout of the control block is up to the library. std::make_shared usually puts the object and its control block in one allocation; the standard recommends this and the common libraries (libstdc++, libc++, MSVC) do it. std::shared_ptr<int>(new int(5)) needs at least two.