What You'll Learn
- How new/delete work internally
- Placement new for custom memory
- Writing a simple pool allocator
- When to use custom allocators
Memory Allocation Internals
Every new call triggers a chain: the compiler calls operator new, which typically calls malloc, which asks the OS for memory via sbrk or mmap. Understanding this chain lets you write allocators that skip the overhead for hot paths.
How new and delete Really Work
When you write int* p = new int(42), three things happen: (1) operator new(sizeof(int)) allocates raw bytes, (2) the constructor runs in that memory, (3) the typed pointer is returned. delete reverses the process — destructor first, then operator delete frees the bytes.
For arrays, new[] stores the element count just before the first element so delete[] knows how many destructors to call. This is why mixing delete and delete[] is undefined behaviour — the count metadata is missing or misinterpreted.
Pro Tip: Use new(std::nothrow) to get nullptr on failure instead of a thrown std::bad_alloc exception — useful in embedded systems or tight loops.
new / delete Mechanics
Allocate single objects, arrays, and test nothrow allocation
#include <iostream>
using namespace std;
int main() {
// Single object allocation
int* p = new int(42);
cout << "Value: " << *p << endl;
cout << "Address: " << p << endl;
delete p; // free the memory
// Array allocation
int* arr = new int[5]{10, 20, 30, 40, 50};
for (int i = 0; i < 5; i++)
cout << arr[i] << " ";
cout << endl;
delete[] arr; // free array memory
// new with nothrow — returns nullptr on failure
int* big = new(nothrow) int
...Placement new — Construct Without Allocating
Placement new separates allocation from construction. You provide a pre-allocated buffer, and placement new calls the constructor in that exact location. This is the foundation of every custom allocator, memory pool, and arena.
The key rule: when you use placement new, you must call the destructor manually. You never call delete on placement-new'd objects because you own the underlying memory separately.
Common Mistake: Forgetting alignas when using placement new. Misaligned memory causes undefined behaviour on most architectures.
Placement new
Construct objects in a pre-allocated stack buffer
#include <iostream>
#include <new> // for placement new
using namespace std;
struct Sensor {
int id;
double reading;
Sensor(int i, double r) : id(i), reading(r) {
cout << "Sensor " << id << " constructed" << endl;
}
~Sensor() {
cout << "Sensor " << id << " destroyed" << endl;
}
};
int main() {
// Pre-allocate raw memory buffer
alignas(Sensor) char buffer[sizeof(Sensor) * 3];
// Construct objects in the buffer (placement new)
Sensor* s1
...Writing a Simple Pool Allocator
A pool allocator pre-allocates a block of fixed-size slots. Allocation is O(1) — just pop from the free list. Deallocation is O(1) — push back onto the free list. No fragmentation, no system calls, no overhead.
Pool allocators are ideal when you create and destroy many objects of the same type — particle systems, network packets, game entities. The standard allocator's general-purpose overhead becomes the bottleneck in these scenarios.
Pool Allocator
Build a simple free-list pool allocator from scratch
#include <iostream>
#include <vector>
#include <memory>
using namespace std;
// Simple pool allocator — pre-allocates a block
template<typename T, size_t PoolSize = 64>
class PoolAllocator {
union Slot { T value; Slot* next; };
Slot pool[PoolSize];
Slot* freeList;
public:
PoolAllocator() {
freeList = &pool[0];
for (size_t i = 0; i < PoolSize - 1; i++)
pool[i].next = &pool[i + 1];
pool[PoolSize - 1].next = nullptr;
}
T* allocate() {
...Quick Reference
| Technique | Use Case |
|---|---|
| new / delete | General heap allocation |
| new(nothrow) | Allocation without exceptions |
| placement new | Construct in pre-allocated memory |
| Pool allocator | Many same-size allocations |
| Arena allocator | Bulk allocate, free all at once |
Lesson Complete!
You now understand how C++ allocates memory internally and can write custom allocators for performance-critical code.
Sign up for free to track which lessons you've completed and get learning reminders.