5.2.12 · D3C++ Programming

Worked examples — Smart pointers — unique_ptr (sole ownership), shared_ptr (shared ownership, ref count), weak_ptr (break cycles)

3,233 words15 min readBack to topic

This page is the practice arena for the parent topic. We will not re-explain the theory — instead we take the full space of situations smart pointers can land you in and work each one to the end, watching the reference count tick like a stopwatch.

Before any code, one word you must own: the reference count (also called the strong count). It is just an integer stored next to the object that says "how many owners are alive right now". Each new owner adds ; each dying owner subtracts ; at the object is deleted. That single counter is the heartbeat of everything below. See Reference-counting if the idea is new.


The scenario matrix

Every problem in this topic is one of these cells. The examples afterwards each announce which cell they fill, and together they cover the whole grid.

Cell What varies The tricky part
A. unique — happy path one owner, scope exit destructor fires exactly once
B. unique — move transfer ownership hops object→object source becomes nullptr
C. unique — the "zero" / empty case pointer holds nothing dereferencing a nullptr
D. shared — count goes up then down copies enter/leave scopes count returns to where it started
E. shared — the double control-block trap two shared_ptr from one raw count splits, double-free
F. weak — object still alive lock() succeeds count momentarily
G. weak — object already gone (expired) last owner died first lock() returns empty
H. the cycle (degenerate/leak) A↔B both strong count never reaches
I. real-world word problem observer cache mix of shared + weak
J. exam twist count arithmetic under nesting predict the exact integer

Two of these are "limiting / degenerate" cases you must never skip: C (the empty pointer — the zero input) and H (the cycle — the count that limits to instead of ). We give both their own figure.


Example 1 — Cell A: unique_ptr, the happy path


Example 2 — Cell B: move transfer, source becomes empty


Example 3 — Cell C: the empty / "zero" case (degenerate input)

Figure — Smart pointers — unique_ptr (sole ownership), shared_ptr (shared ownership, ref count), weak_ptr (break cycles)

Example 4 — Cell D: shared_ptr count up then back down


Example 5 — Cell E: the double control-block trap


Example 6 — Cell F: weak_ptr.lock() while the object lives


Example 7 — Cell G: weak_ptr expired (object already gone)


Example 8 — Cell H: the reference cycle (degenerate leak)

Figure — Smart pointers — unique_ptr (sole ownership), shared_ptr (shared ownership, ref count), weak_ptr (break cycles)

Example 9 — Cell I: real-world word problem (observer cache)


Example 10 — Cell J: exam twist, predict the exact integer


Recall Rebuild the matrix from memory

Which cell is the "count limits to 1, never 0" leak? ::: Cell H — the reference cycle; fix with a weak_ptr on one edge. Which cell is the degenerate empty input, and how do you use it safely? ::: Cell C — a default unique_ptr holds nullptr; guard with if (p) before *p. Does copying a shared_ptr change the strong count? Does moving it? ::: Copy: +1. Move: unchanged (transfers the existing owner, empties the source). Why do two shared_ptrs from one raw pointer double-free? ::: They build two independent control blocks; each count is ; each deletes the same object.