5.02 Pass-by-Value Copy Overhead vs Pass-by-Reference & const& in Microcontroller RAM
Executive Summary: Comprehensive comparative study of the three parameter passing schemes: pass-by-value, pass-by-reference (&), and pass-by-const-reference (const &). We analyze assembly instruction differences, stack frame memory consumption, and reference aliasing in safety-critical systems.
💻 1. Annotated Source Code
#include <iostream> using namespace std; void valueChanged1(int someNum); void valueChanged2(int& someNum); // & means 'pass by reference' int main() { int myNumber = 20; cout << "Before valueChanged1 call, myNumber is " << myNumber << endl; valueChanged1(myNumber); cout << "After valueChanged1 call, myNumber is " << myNumber << endl; cout << "\n-------------------------------------------\n"; cout << "Before valueChanged2 call, myNumber is " << myNumber << endl; valueChanged2(myNumber); cout << "After valueChanged2 call, myNumber is " << myNumber << endl; return 0; } void valueChanged1(int someNum) { someNum = 100; cout << "Inside valueChanged1, someNum is " << someNum << endl; } void valueChanged2(int& someNum) { someNum = 100; cout << "Inside valueChanged2, someNum is " << someNum << endl; }
📐 2. Architecture & UML Class Model
<<compilation-unit>>
PassingSchemesUnit
Calling Convention
Attributes / Data Members
(none / stateless)
Operations / Methods
+passByValue(x: int32_t) : void (Local register copy in R0)
+passByRef(x: int32_t&) : void (Passes memory address, stores via STR)
+passByConstRef(x: const int32_t&) : void (Zero-copy read-only)
📚 3. Core C++ Concepts Deep-Dive
1. Pass-by-Value
A complete copy of the argument is constructed in the callee's stack frame. Modifications inside the function do NOT affect the caller's variable.
2. Pass-by-Reference (T&)
Passes an alias (internally implemented as a pointer). Modifications inside the function directly alter the caller's variable.
3. Pass-by-Const-Reference (const T&)
Passes an alias with read-only guarantees. Prevents copying large structures while preventing accidental modifications.
⚡ 4. Embedded Systems & Hardware Reality
1. The Embedded Rule of Thumb
- Primitive Types ($\le 4$ bytes): Pass by value (
int,float,uint32_t). They fit directly inside CPU registers (R0-R3), requiring zero pointer indirection. - Aggregates & Structs ($> 4$ bytes): Pass by const reference (
const SensorPacket&). Passing by value copies bytes onto the stack, increasing execution time and RAM usage.
💡 5. Production-Ready Embedded Refactoring
Idiomatic passing schemes in embedded systems:
💡 Production-Ready Refactor
#include <cstdint> struct CanMessage { uint32_t id; uint8_t payload[8]; uint8_t dlc; }; // 1. Primitive: Pass-by-value (fits in R0) void setFilterId(uint32_t id) noexcept; // 2. Struct: Pass-by-const-ref (passes 4-byte pointer; avoids 16-byte copy) void transmitCan(const CanMessage& msg) noexcept; // 3. Mutator: Pass-by-ref (modifies caller's object directly) void readCan(CanMessage& out_msg) noexcept;
📝 Knowledge Verification Quiz
Test your understanding of the C++ concepts and embedded microcontroller trade-offs covered in this guide. Click any option for instant feedback.
Q1. Why is passing a 64-byte telemetry struct by value suboptimal on an embedded microcontroller?
Detailed Explanation:
Pass-by-value creates a full duplicate of the struct on the stack, consuming stack RAM and CPU cycles for memory copying.
Q2. For a 32-bit integer (uint32_t), why is pass-by-value generally faster than pass-by-const-reference on ARM Cortex-M?
Detailed Explanation:
Passing a 4-byte integer by value puts it directly into a register (R0), while passing by reference passes a pointer that forces an extra
LDR memory read.
Q3. What is 'pointer aliasing' in C++ parameter passing?
Detailed Explanation:
Aliasing occurs when multiple pointers/references refer to the same object. The compiler must assume writes through one pointer may modify the other, limiting optimization.
Q4. What does passing by non-const reference (T&) signal in function API design?
Detailed Explanation:
Non-const reference parameters (
T&) indicate that the function will mutate the caller's object in place.