4.09 Capacity vs Size, Geometric Growth Reallocation & Real-Time Heap Hazards
💻 1. Annotated Source Code
#include <iostream> #include <string> #include <vector> using namespace std; int main() { vector<int> someVec; vector<string> anotherVec(3); someVec.push_back(1); someVec.push_back(2); someVec.push_back(3); cout << "someVec size: " << someVec.size() << endl; anotherVec[0] = "John"; anotherVec[1] = "Bob"; anotherVec[2] = "Sally"; anotherVec.push_back("Shannon"); for (int val : someVec) { cout << val << endl; } cout << endl; for (string name : anotherVec) { cout << name << endl; } cout << endl; cout << "Front and back of anotherVec:" << endl; cout << "front: " << anotherVec.front() << endl; cout << "back: " << anotherVec.back() << endl; anotherVec.pop_back(); anotherVec.insert(anotherVec.begin(), "Don"); cout << "\nAfter modification: " << endl; cout << "front: " << anotherVec.front() << endl; cout << "back: " << anotherVec.back() << endl; return 0; }
📐 2. Architecture & UML Class Model
📚 3. Core C++ Concepts Deep-Dive
1. Size vs Capacity
- Size: The number of active elements currently in the vector (
.size()). - Capacity: The total number of elements allocated in heap memory before reallocation is needed (
.capacity()).
2. Geometric Growth & Iterator Invalidation
When push_back() exceeds current capacity, std::vector allocates a new heap buffer (typically $1.5\times$ or $2\times$ larger), copies/moves all existing elements, and frees the old buffer. All existing pointers and iterators to elements are invalidated!
⚡ 4. Embedded Systems & Hardware Reality
1. Real-Time Latency Spikes during Vector Growth
A push_back() is usually $O(1)$ amortized, but when reallocation occurs, it spikes to $O(N)$ with dynamic heap allocation latency, causing missed real-time deadlines in motor control or audio processing loops.
2. Memory Fragmentation
Repeated vector expansion allocates and frees progressively larger blocks, causing severe heap fragmentation on constrained SRAM microcontrollers.
💡 5. Production-Ready Embedded Refactoring
Pre-reserving capacity or using fixed-capacity bounded vectors:
#include <vector> // If std::vector MUST be used, reserve capacity upfront at boot std::vector<int> createTelemetryVector(size_t expected_items) { std::vector<int> vec; vec.reserve(expected_items); // Allocates ONCE; eliminates dynamic reallocations return vec; }
📝 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.
std::vector reallocates a larger memory block on the heap, moves existing elements, and frees the old block, invalidating all existing references/iterators.
reserve() allocates the requested capacity in a single initial allocation, ensuring subsequent push_back() operations run in deterministic $O(1)$ time without reallocation.