5.2.11 · D1C++ Programming

Foundations — Rule of Zero — prefer compiler-generated specials

1,666 words8 min readBack to topic

This page is the ground floor. The parent note assumes you already know what a "class", a "member", a "pointer", "copy vs move", a "destructor", and "RAII" are. If any of those words feels fuzzy, read here first — every one is built from nothing.


0. What is a class and a member? (the container picture)

Picture a box with labelled slots. The box is the object (a thing built from the class blueprint); each slot holds one member.

Figure — Rule of Zero — prefer compiler-generated specials
Members
the individual data pieces stored inside an object.

1. Value vs. resource — the two kinds of slot

Some slots hold a plain value (a number). Some slots hold a handle to a resource — memory grabbed from the operating system, an open file, a network socket. A value is self-contained. A resource lives elsewhere, and the slot only holds a ticket pointing to it.

Figure — Rule of Zero — prefer compiler-generated specials

Why the topic needs this: the whole Rule of Zero hinges on the difference. Copying a value slot is trivially safe; copying a handle slot is where all the danger lives.


2. The pointer * and new / delete — the "ticket to elsewhere"

Pointer int* p
a variable holding the address of an int living elsewhere.
delete[] p run twice on the same address
a double-free — undefined behaviour / crash.

3. Copy vs. Move — two ways to "get another one"

This is the heart of the vocabulary. Suppose a box A holds a resource and we want a box B.

Figure — Rule of Zero — prefer compiler-generated specials
Deep copy
B gets its own resource holding the same contents; A unchanged.
Move
A's resource is handed to B; A is left empty but destructible.

4. The Special Member Functions (the "Big Five")

Every class secretly needs answers to these questions. If you don't write them, the compiler writes a default. These are the special member functions.

Decoding the notation, symbol by symbol:

  • ~T() — the tilde ~ marks the destructor. Read "the un-maker of T".
  • const T& — a reference (&) to an existing T we promise not to change (const). Used for copy: we read the source without touching it.
  • T&& — a double ampersand marks an rvalue reference: a reference to something the compiler knows is temporary / about to die. This is the signal "you may safely steal from me" — the trigger for a move. (Deeper dive: Move semantics and rvalue references.)
~T()
the destructor — cleanup code run when the object dies.
const T&
a read-only reference to an existing object (used by copy).
T&&
an rvalue reference — a handle to a temporary that may be safely stolen from (used by move).

5. RAII — the trick that makes slots self-managing

An RAII wrapper is a small class whose whole job is to hold one resource and know its five behaviours. The standard library ships several:

  • std::string, std::vector — own heap memory; deep-copy, cheap-move, auto-free.
  • std::unique_ptr — sole owner of one heap object; move-only.
  • std::shared_ptr — shared owner; copy = share.
RAII
acquire in constructor, release in destructor — cleanup happens automatically at scope exit.
Why RAII members give Rule of Zero
their own five functions are already correct, so memberwise generation is correct.

The prerequisite map

class and members

value vs resource

pointer new and delete

double free hazard

copy vs move

the Big Five specials

RAII self managing members

Rule of Zero

Read it bottom-up: the box-of-slots idea leads to the value/resource split; resources need pointers, which create the double-free danger; that danger is exactly what the Big Five must tame; RAII members tame it for you; and that is the Rule of Zero.


Equipment checklist

Test yourself — cover the right side and answer before revealing.

An object vs. a class
a class is the blueprint; an object is one box built from it.
A member
one data slot stored inside an object.
Value type vs. handle
a value is its data; a handle only points at data living elsewhere.
What int* p stores
the address of an int, not the int itself.
What delete[] p must never do
run twice on the same address (double-free).
Deep copy
duplicate the pointed-to data so the two objects share nothing mutable.
Move
hand the resource over and leave the source empty-but-destructible.
The Big Five
destructor, copy-ctor, copy-assign, move-ctor, move-assign.
Meaning of ~T()
the destructor, run at end of the object's life.
Meaning of const T&
read-only reference to an existing object (copy source).
Meaning of T&&
rvalue reference — a temporary you may steal from (move source).
"Memberwise" generation
the compiler's default copies/moves/destroys each member using that member's own function.
RAII
acquire in the constructor, release in the destructor, automatically.
Why RAII members give you Rule of Zero
each member is already correct, so the compiler-generated whole is correct too.