5.2.12 · D1C++ Programming

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

1,930 words9 min readBack to topic

Before you can read a single line of the parent topic, you must own every symbol it silently assumes. This page builds them one at a time, from absolute zero. Nothing is used before it is earned.


1. Memory, addresses, and the object

Picture your computer's memory as a very long street of numbered houses. Each house holds one byte. Every house has a number — that number is called an address.

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

2. The raw pointer T*

So int* p; reads left-to-right as "p is a pointer to an int" — p is an arrow that can point at a house holding an int.

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

3. new, delete, and where the leak comes from

Memory comes in two neighbourhoods. Most variables live on the stack: they are created when you enter a { } block and destroyed automatically when you leave it. But sometimes you need a house that outlives the block that made it. For that you ask the system for a house from the heap.

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

4. Scope, lifetime, and the destructor

This is the mechanism that makes smart pointers work, so we build it carefully.

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

5. Copy vs move — why unique_ptr can't be copied


6. Reference counting — the tally sheet

The parent's shared_ptr rests on one idea: Reference-counting.


7. std::, <memory>, and make_ factories


Prerequisite map

Memory as numbered houses

Address

Raw pointer T-star

new and delete

Memory leak

Scope and lifetime

Constructor and destructor

RAII

Copy vs move

unique_ptr

Reference count

shared_ptr

Cycle leak

weak_ptr

Smart pointers topic

Each arrow means "you must understand the tail before the head makes sense." Follow any path top-to-bottom and you arrive at the topic with no gaps.


Equipment checklist

Read the left side, answer out loud, then reveal.

What does a raw pointer T* actually store?
Just a number — the address of a house in memory; it says where, never who owns it.
What does *p do, and how is it the reverse of &x?
*p reads the value at the address p holds (address → value); &x gives the address of x (value → address).
Why does a heap object leak when its block ends?
Only the stack pointer variable dies; the heap house stays, but its address is lost, so nobody can delete it.
When exactly does a destructor run?
Automatically the moment the object dies — closing }, early return, or thrown exception — which is why delete inside it can't be forgotten.
Why can two owners copying one raw pointer crash?
Both destructors call delete on the same house → double-free.
What does std::move(x) really do?
Nothing by itself — it's a cast that labels x as "steal-from-able", enabling the move that empties the source.
When does reference counting delete the object?
When the count reaches 0 — the last owner has left.
Why can't plain reference counting free a cycle?
A and B keep each other's count at 1, so neither ever reaches 0.
Why prefer make_unique / make_shared over bare new?
They allocate + construct + wrap in one call, leaving no raw new to leak and staying exception-safe.