Stack, Heap, and Lifetime
Where objects live, when they die, and why the lifetime question precedes every pointer question.
Two homes for objects
The stack โ automatic storage. Local variables live here; the compiler allocates and frees them:
void f() {
int x{5}; // born when the line runs
std::vector<int> v{1, 2, 3}; // born; its ELEMENTS live on the heap (below)
} // both die here โ guaranteed, reverse order
Stack allocation is nearly free and lifetimes are exact: enter scope โ live; leave scope โ dead. Every local, nested, and temporary object follows this rule.
The heap โ dynamic storage for things whose size or lifetime must be decided at runtime. The vector's elements, a std::string's characters, objects shared between scopes: their contents live on the heap, but their handles (the vector/string object itself) are still stack locals.
The lifetime question โ ask it first
For every object: who is allowed to use it, and until when?
stack local โ lives to end of scope (automatic)
heap object โ lives until SOMETHING releases it (the next lessons: what and how)
The three classic bugs (know their names)
- Memory leak โ heap memory allocated, never released; the program slowly bloats.
- Use-after-free / dangling โ using memory that was already released.
- Double-free โ releasing the same memory twice.
Every one of them is an ownership mistake: either nobody owned the memory, or two things thought they did. The cure is not vigilance; it is making ownership explicit and automatic โ which is exactly RAII.