Stack vs Heap Allocation

Stack allocation eliminates explicit storage management and is more efficient than heap allocation — prefer it whenever the object’s lifetime matches its enclosing block.

Why is stack allocation faster than heap allocation?

The heap has to maintain a data structure (e.g. a free list) to track used/free blocks and search for a suitable block on every malloc. The stack just follows LIFO: the size is known at compile time (or frame-entry time) and allocation is a single pointer bump. See Heap (Memory) for the full allocator story.

When heap allocation is required

Four cases where stack allocation is impossible:

  1. Storage must outlive the block in which it’s allocated — i.e. ownership transfers out of the frame.
  2. The amount of data is unknown at compile time (e.g. C++ Vector growing arbitrarily).
  3. An array of objects must be initialized via constructors with different arguments per element.
  4. Large local variables that would blow a small stack.

Case 3 worked example

This does not compile if Obj has no default constructor, or if its fields are const:

Obj obj[10];                    // declaration fails — no default ctor
for ( int id = 0; id < 10; id += 1 )
    obj[id].id = id;            // assignment fails — Obj::id is const

Forced into heap pointers:

Obj * objs[size];
for ( int id = 0; id < size; id += 1 )
    objs[id] = new Obj{ id };
for ( int id = 0; id < size; id += 1 )
    delete objs[id];

uC++ escape hatch: uArray

uC++ provides a uArray macro that gives you stack-allocated, dynamically-sized arrays with deferred construction — sidestepping case 3 for many use cases:

{
    cin >> size;
    uArray( Obj, objs, size );  // macro, stack-allocated
    for ( int id = 0; id < size; id += 1 )
        objs[id]( id );          // constructor call
    ...
}   // implicit array deallocate