Every value your program uses lives somewhere in memory. Where it lives determines how long it lives, how fast it is to access, and who is responsible for cleaning it up. This is the module that separates people who "know C++ syntax" from people who understand C++.
The stack
Local variables live on the stack: a region of memory that grows and shrinks automatically as functions are called and return. When you declare int x = 5; inside a function, x is placed on the stack. When the function returns, x is automatically gone. No cleanup code needed.
void f() {
int a = 1; // on the stack
double b = 2.0; // on the stack
} // a and b are destroyed here, automatically, in reverse orderStack allocation is extremely fast — it's just moving a pointer. But the stack is small (typically a few MB) and its objects can't outlive the function that created them.
The heap
The heap (also called free store) is a large region for objects whose size or lifetime you control at runtime. You request memory with new and must return it with delete.
int* p = new int(42); // allocate one int on the heap, p holds its address
std::cout << *p; // dereference: read the value at that address
delete p; // return the memory. Forgetting this = leak.Heap memory persists until you delete it — it survives across function returns. That power comes with responsibility, and that responsibility is where nearly every classic C++ bug comes from.
The three deadly sins of manual memory
// SIN 1: memory leak — allocated but never freed
void leak() { int* p = new int(1); } // p vanishes; the int is orphaned forever
// SIN 2: use-after-free — using memory you already freed
int* p = new int(1);
delete p;
std::cout << *p; // UNDEFINED behavior — p is dangling
// SIN 3: double-free — freeing the same memory twice
int* q = new int(1);
delete q;
delete q; // UNDEFINED behavior — corruption or crashEvery one of these three is a favorite interview trap, and the Akuna debugging round is built on spotting them in unfamiliar code. You will train this explicitly in Module 11. For now, learn to feel uneasy every time you see a raw new — because someone has to delete it, exactly once, on every path including exceptions.
Why you'll rarely write new and delete
Modern C++ almost never uses raw new/delete in application code. Instead we use:
- Stack objects whenever possible — automatic cleanup, zero bugs.
- Containers like
std::vector(Module 07) that manage heap memory for you. - Smart pointers like
std::unique_ptr(Module 06) thatdeleteautomatically when they go out of scope.
The reason is RAII (Resource Acquisition Is Initialization): tie a resource's lifetime to an object's scope, and let the destructor free it. You'll learn to build RAII types yourself in Module 04. But the intuition starts here: manual memory management is error-prone, so we let scope and destructors do it.
A pointer is just a variable holding an address — a number naming a location in memory. *p means "the value at that address." &x means "the address of x." That's the whole concept. Module 03 makes it concrete.
Exercise 02.1 — Watch the lifetime
Make object lifetime visible:
- Write a struct with a constructor that prints
"born"and a destructor that prints"died"(you'll formalize these in Module 04; for now juststruct Noisy { Noisy(){...} ~Noisy(){...} };). - Create one on the stack inside a function and observe when "died" prints.
- Create one with
newand observe that "died" only prints when youdeleteit — and never prints if you forget. - Create two on the stack in the same scope and confirm they're destroyed in reverse order.
Takeaways
- Stack: automatic, fast, small, tied to scope. Heap: manual, large, lifetime you control.
- Raw
newdemands exactly one matchingdeleteon every path. - The three sins: leak, use-after-free, double-free. All are undefined behavior (except leak, which is "just" a resource bug).
- Prefer stack objects, containers, and smart pointers over manual memory.
- RAII ties resource lifetime to scope. It's the reason well-written C++ rarely leaks.
Loading starter code…
Checkpoint · Memory Model
5 questions · pass at 70%
int* p = new int(1); delete p; std::cout << *p;Finished Module 02?
Pass the quiz to complete it automatically.