Embedded C++ Subset
Introduction
C++ on a laptop can use exceptions, gigabytes of heap, and the full standard library. Your MCU has tens to hundreds of kilobytes of flash, limited RAM, no MMU, and hard real-time deadlines. Professional embedded C++ is not "all of C++" — it is C++ with features switched off or restricted on purpose.
This article gives practical rules: what to use freely, what to gate carefully, and what many teams ban in safety-related firmware.
The embedded C++ mindset
Same silicon as C firmware. Extra C++ features must earn their flash, RAM, and determinism cost.
1 2 | |
In plain terms
C++ on MCU is a toolbox, not the whole hardware store. You bring a small bag: hammer (classes), tape (RAII), labels (namespaces). You leave the crane (exceptions, heavy STL) at home unless the project truly needs it.
Feature guide
| Feature | Typical on MCU | Notes |
|---|---|---|
| Classes / RAII | Yes | Core win |
References / const |
Yes | Low cost |
| Namespaces | Yes | Organization |
enum class |
Yes | Safer than C enum |
| Templates (limited) | Careful | Watch flash |
new / delete |
Rare / pool | Fragmentation risk |
| Exceptions | Usually off | -fno-exceptions; table cost |
| RTTI | Usually off | -fno-rtti; dynamic_cast gone |
std::iostream |
Usually no | Large; use UART printf |
std::vector / strings |
Linux class MCUs only | Heap; use fixed buffers |
Threads (std::thread) |
Prefer RTOS API | FreeRTOS, Zephyr |
| Virtual functions | Sparingly | vtable per class |
Compiler flags you will see
1 | |
| Flag | Effect |
|---|---|
-fno-exceptions |
No try/catch; smaller binary |
-fno-rtti |
No runtime type info |
-Os |
Optimize size |
-ffunction-sections |
Linker garbage-collect unused |
Arduino and PlatformIO often set these implicitly on AVR/ARM; verify in verbose build log.
Exceptions — usually disabled
1 2 3 4 5 | |
With -fno-exceptions, this does not compile or is transformed away. Error handling on MCU:
- Return error codes (
enum class Error) - Optional
std::optional(C++17) on larger targets - Assertions in debug builds
- Safe state + watchdog on fault
Same discipline as good C firmware — C++ does not require exceptions.
Dynamic memory
Dynamic memory and I/O applies: heap may be small. C++ adds:
new/delete— avoid in ISRs and tight loopsstd::string,std::vector— allocate under the hood- Smart pointers — still use heap unless custom deleter + pool
Preferred:
- Static buffers (
std::array, C arrays) - Memory pools for fixed-size objects
- Placement new on pre-allocated arena (advanced)
Static initialization
Global C++ objects with constructors run before main:
1 | |
Order across files is undefined. Many teams:
- Use
init()called from startup code after clocks and HAL - Keep globals POD or trivial
- Document any allowed static constructors
Virtual functions — cost of indirection
1 2 3 4 5 6 7 8 9 | |
Each object with virtual methods has a vtable pointer — extra RAM per object, indirect call cost. Fine for polymorphic drivers on Linux; on 8 KB RAM MCU, prefer compile-time polymorphism (templates) or plain C function pointers you already know from Pointers in depth.
enum class — use this
1 2 3 4 | |
Scoped enumerations prevent the classic C bug if (state = Running).
Mixing with C HAL — recap
- HAL in C (
.c/.h) - Application in C++ (
.cpp) extern "C"includes- No exceptions across C boundaries
- Callbacks: function pointers still valid
Style guides and MISRA
Automotive and medical projects use MISRA C++ or house rules: subset of language, required patterns, banned constructs. Even student projects benefit from a short team coding standard (naming, no naked new, const discipline).
Arduino / PlatformIO note
Sketches are C++ (setup/loop are functions, Serial is an object). Hiding under the hood: classes, inheritance, some STL. Learning "real" embedded C++ means understanding what the core does without copying every convenience feature to a bare STM32 project.
Relevant topics
- Introduction to C++
- Constructors, RAII, and destructors
- Templates and generic code
- Real-time systems
- Firmware architecture
Starting points
- Read build flags for your board — note
-fno-exceptions,-std=. - Audit one project for
new,std::string, virtual — list flash/RAM risks. - Rewrite one error path from hypothetical
throwtoenum classreturn. - Compare binary size: same logic in C vs minimal C++ class with RAII.
Focus points
- Subset by policy — document what your team allows.
- Measure after enabling templates or virtual hierarchies.
- RTOS APIs over
std::threadon typical MCU. - Safety — no exceptions in ISRs; deterministic failure modes.
Key points
- Embedded C++ uses a restricted feature set focused on classes, RAII, and compile-time safety.
- Exceptions and RTTI are usually disabled; error codes and RAII replace them.
- Heap and STL containers are limited; static and pool allocation dominate on MCU.
- Know your flags and style guide — C++ power requires discipline on small targets.