Stack vs heap in C++: where your variables actually live

Short answer: ordinary local variables live on the stack β€” allocated in nanoseconds, destroyed automatically when their scope ends. The heap is for things that must outlive their scope or be sized at runtime β€” bigger and flexible, but allocated explicitly and cleaned up by you.

Watch the lifetime difference run

The function below has a local variable and the program has a global. Call the function three times and watch what each remembers:

#include <iostream>
using namespace std;

int counter = 0;   // global: lives for the whole program

void bump() {
    int local = 0; // stack: recreated on every call
    local++;
    counter++;
    cout << "local=" << local << " counter=" << counter << endl;
}

int main() {
    bump();
    bump();
    bump();
    return 0;
}

local prints 1 every single time β€” it's born, lives and dies within one call of bump(), on the stack. counter keeps its value across calls because its lifetime is the whole program. Lifetime is the heart of the stack/heap distinction.

Side by side

StackHeap
Who allocatesAutomatic β€” just declare itYou β€” new (or a container/smart pointer)
LifetimeEnds when the scope endsUntil you delete it (or its owner dies)
SpeedExtremely fast (one pointer move)Slower (bookkeeping, searching for space)
SizeSmall β€” typically ~1–8 MBBasically "available RAM"
Dies when?Scope exit β€” guaranteedOnly if you free it β€” else: leak
Typical useLocals, function parametersBig data, runtime-sized data, shared objects

Heap allocation: new and delete

(Our in-browser engine doesn't support new/delete yet β€” run this one on your desktop compiler.)

int main() {
    int* p = new int(42);   // allocate on the heap, p holds the address
    cout << *p << endl;     // 42
    delete p;               // give the memory back β€” your job, not the scope's
    return 0;
}

Every new must be matched by exactly one delete. Miss the delete β†’ memory leak (memory you can never reach or reuse). delete twice, or keep using the pointer after deleting (a dangling pointer) β†’ undefined behavior.

The modern answer: you rarely call new/delete by hand

C++'s superpower for this problem is RAII β€” Resource Acquisition Is Initialization: tie the resource's lifetime to an object's scope, and the scope guarantees cleanup. You've already used RAII without the name: a std::vector manages its heap array automatically. For single objects, the same job is done by smart pointers:

#include <memory>

int main() {
    auto p = std::make_unique<int>(42);  // heap memory, owned by p
    cout << *p << endl;                  // 42
    return 0;                            // p dies here β€” memory freed automatically
}

Rule of thumb for modern code: stack by default; heap through an owner (vector, string, unique_ptr) β€” almost never raw new/delete.

Two famous failure modes

Interview questions on this theme

  1. "What lives on the stack vs the heap?" β€” locals/parameters vs explicitly allocated data (and what vectors/strings manage for you under the hood).
  2. "Why is stack allocation fast?" β€” it's just moving one stack pointer; heap allocation needs bookkeeping and a search for free space.
  3. "What is a memory leak, in one sentence?" β€” heap memory that's unreachable and will never be freed.
  4. "What is RAII?" β€” bind resource lifetime to object scope so cleanup is automatic; it's how vector, string, fstream and smart pointers all work.
  5. "Why is returning a reference/pointer to a local variable broken?" β€” the lifetime question that starts this article, weaponized.

Practice in the playground

  1. Modify the lifetime demo: add a second global and a second local; predict all six output lines before running.
  2. Write int* broken() { int x = 7; return &x; } β€” don't run it (undefined behavior!); instead, explain in one comment line why a desktop compiler warns about it.
  3. Recursion depth: the Fibonacci example with fib(10) is safe; reason about roughly how deep fib's stack goes and why fib(100000) would be a stack overflow.

Related: pass by value vs pointer vs reference, what int main() is, 15 beginner interview questions.