- References
- Function Overloading
- Default Function Arguments
- Inline Function
- Dynamic Memory Allocation
- Placement New
- nullptr
- Namespaces
- Type Aliases
- Enum classes
- constexpr
- static_assert
- mutable Keyword
- auto Keyword
- Smart Pointers
- Basics of Classes
- Constructors
- Destructors
- Operator Overloading
- Copy Semantics
- Move Semantics
- Composition, RAII & Ownership
- Inheritance
- Polymorphism
- Abstraction
- Encapsulation
- Template
- Static Memory
- Friend Function
- this Pointer
- Function Pointer
- Lambdas and Callback Management
- Union
Placement New (Static Allocation Constructor)

Standard new allocates memory on the Heap and then constructs the object.
Placement New separates these steps. It allows you to construct an object in a pre-allocated memory buffer (Stack, Static, or a specific hardware address) that you explicitly provide.
This is the standard way to use C++ objects in strict embedded systems where the Heap is banned.
Syntax & Usage
1. Basic Setup
You need a memory buffer (usually a byte array) large enough to hold the object.
Note: You must include <new> to use this.
#include <new>
class Sensor {
public:
int id;
Sensor(int i) : id(i) { printf("Init\n"); }
~Sensor() { printf("De-init\n"); }
};
// 1. Allocate raw memory (Static buffer)
// 'alignas' prevents bus faults by ensuring correct memory alignment
alignas(Sensor) uint8_t buffer[sizeof(Sensor)];
int main() {
// 2. Use Placement New
// Syntax: new (address) Type(args);
Sensor* s = new (buffer) Sensor(10);
// s->id is now 10, stored inside 'buffer'
}2. Manual Destruction
Because you didn't allocate memory with standard new, you cannot use standard delete. You must call the destructor manually.
// ❌ delete s; // CRASH! Tries to free static memory to the heap manager.
s->~Sensor(); // ✅ Correct: Cleans up the object, leaves memory alone.Memory Visualization
Standard new finds a random spot in the Heap. Placement new puts the object exactly where you say.
| Standard new Sensor() | Placement new (buf) Sensor() |
|---|---|
Step 1: Ask Heap Manager for sizeof(Sensor) bytes. | Step 1: User provides address of buffer. |
| Step 2: Construct object in that heap memory. | Step 2: Construct object in buffer. |
| Result: Pointer to dynamic heap memory. | Result: Pointer to your static buffer. |
Relevance in Embedded/Firmware
1. No Heap Required
You can have full C++ objects (with constructors, v-tables, and inheritance) stored entirely in Static Memory (.bss). This makes your firmware deterministic and fragmentation-free, satisfying safety standards (MISRA, ISO26262).
2. Memory-Mapped Objects
You can place an object directly onto a hardware register or a specific memory region (e.g., backup SRAM or shared memory between cores).
// Construct a Driver object exactly at the hardware address 0x40005000
UART_Driver* uart1 = new (reinterpret_cast<void*>(0x40005000)) UART_Driver();3. Object Pools
If you need to create/destroy objects frequently (e.g., Network Packets), use a pre-allocated array of buffers (a Pool). Use placement new to construct a packet in slot 0, manually destroy it, and then reuse slot 0 for a new packet later.
Common Pitfalls (Practical Tips)
| Pitfall | Details |
|---|---|
| ❌ Memory Alignment | If your buffer is just Fix: Always use |
❌ Using delete | Calling delete on a placement-new pointer will confuse the memory manager (allocator), likely causing a crash or heap corruption. Always use ptr->~Class(). |
| ❌ Buffer Overrun | You must ensure sizeof(buffer) >= sizeof(Object). The compiler won't warn you if the buffer is too small, leading to memory corruption of adjacent variables. |
| ✅ Reusing Memory | Placement new is perfect for "Union-like" behavior where different types of objects reuse the same memory chunk at different times to save RAM. |
Concept understood? Let's apply and learn for real