Basic Memory and Allocation Guide for C++

July 17, 2025

In this post I will explain how new/delete vs malloc/free and std::vector interact with the CPU’s memory hierarchy and why one is faster or slower based on Ulrich Drepper’s memory guide.

operator new vs malloc

std::vector Growth: push_back vs reserve

Compute vs Memory Gap

Practical Recommendations


+------------------------------+--------------------------------------------+------------------------------------------------+--------------------------------------------------+
| Mechanism                    | Overhead                                   | Performance Tips                                 | Best Use Case                                  |
+------------------------------+--------------------------------------------+------------------------------------------------+--------------------------------------------------+
| operator new / delete        | • Heap metadata access                     | • Batch small allocations                        | • Occasional C++ objects needing ctors         |
|                              | • Constructor/destructor calls             | • Consider stack or arena allocators             | • Unpredictable allocation points              |
+------------------------------+--------------------------------------------+------------------------------------------------+--------------------------------------------------+
| malloc / free                | • Heap metadata access                     | • Use for POD data or C interop                  | • Raw buffers or C‑style code paths            |
|                              | • Lock contention in multithreaded programs| • Batch via custom arena or pool                 | • Few, simple allocations                      |
+------------------------------+--------------------------------------------+------------------------------------------------+--------------------------------------------------+
| vector.push_back (no reserve)| • Repeated realloc + copy                  | • Call reserve(N) when N is known                | • Rapid prototyping or small N                 |
|                              | • Cache line & TLB thrash                  | • Minimize number of growth phases               |                                                |
+------------------------------+--------------------------------------------+------------------------------------------------+--------------------------------------------------+
| vector.reserve + push_back   | • Single upfront allocation                | • Leverage spatial locality                      | • Large, fixed‑size arrays                     |
|                              | • Excellent contiguous layout              | • Align to cache‑line (64 B)                     | • High performance loops with known N          |
+------------------------------+--------------------------------------------+------------------------------------------------+--------------------------------------------------+
| Stack / Arena Allocators     | • No heap metadata overhead                | • Use for temporaries; scope‑based lifetimes     | • Short lived, high frequency allocations      |
+------------------------------+--------------------------------------------+------------------------------------------------+--------------------------------------------------+
| Batched Small Allocations    | • Fragmentation & TLB pressure             | • Group related allocations into pools           | • High throughput allocation patterns          |
|                              | • Lock bouncing between cores              | • Reduce lock contention with per‑thread arenas  |                                                |
+------------------------------+--------------------------------------------+------------------------------------------------+--------------------------------------------------+
    

← Back to blog