8.06 Pointer-to-Pointer (Drone**) Fleet Arrays vs Flat Contiguous Array-of-Structures (AoS)
💻 1. Annotated Source Code
#include <iostream> #include "Drone.h" using namespace std; void printFleet(Drone** fleet, int size); int main() { int numDrones = 0; string model; double battery = 0.0; cout << "How many drones are in your fleet? "; cin >> numDrones; Drone** droneFleet = new Drone* [numDrones]; for (int i = 0; i < numDrones; i++) { cout << "Enter model name for drone " << (i + 1) << ": "; cin.get(); getline(cin, model); cout << "Enter battery life (as a percentage) for " << model << ": "; cin >> battery; droneFleet[i] = new Drone(model, battery); } // end of the for loop cout << "\nDrone Fleet Summary:" << endl; printFleet(droneFleet, numDrones); // cleanup for (int i = 0; i < numDrones; i++) { delete droneFleet[i]; droneFleet[i] = nullptr; } delete[] droneFleet; return 0; } void printFleet(Drone** fleet, int size) { for (int i = 0; i < size; i++) { cout << "Drone " << (i + 1) << ": " << fleet[i]->getModelName() << " | Battery: " << fleet[i]->getBatteryLife() << "%" << endl; } }
#ifndef DRONE_H #define DRONE_H #include <string> using namespace std; class Drone { public: Drone(string modelName, double batteryLife); string getModelName() const; double getBatteryLife() const; private: string modelName; double batteryLife; }; #endif
#include "Drone.h" Drone::Drone(string modelName, double batteryLife) { this->modelName = modelName; this->batteryLife = batteryLife; } string Drone::getModelName() const { return modelName; } double Drone::getBatteryLife() const { return batteryLife; }
📐 2. Architecture & UML Class Model
📚 3. Core C++ Concepts Deep-Dive
1. Pointer-to-Pointer Mechanics (Type**)
A pointer-to-pointer stores the memory address of another pointer. In classical C++, dynamic 2D tables or arrays of polymorphic objects are created by allocating an array of pointers (Drone** fleet = new Drone*[N]) and then individually allocating each object (fleet[i] = new Drone(...)).
2. Double Allocation Overhead
Managing $N$ objects requires $N + 1$ distinct heap allocations ($1$ array of pointers $+ N$ individual objects) and $N + 1$ corresponding delete calls.
⚡ 4. Embedded Systems & Hardware Reality
1. The Hardware Cost of Pointer Chasing
Accessing fleet[i]->getBatteryLife() requires double dereferencing:
- Read the pointer from the pointer array:
ptr = *(fleet + i). - Dereference
ptrto read the object in distant heap memory:ptr->battery.
Because each object was allocated separately on the heap, they are scattered randomly across SRAM. On modern pipelined microcontrollers (ARM Cortex-M7 with L1 data cache), this causes frequent cache misses and memory stall cycles.
2. Flat Contiguous Storage: Array of Structures (AoS)
Storing objects contiguously in a single flat array (std::array<Drone, MaxDrones>) requires zero pointer storage (saving $4 \times N$ bytes of RAM) and maximizes CPU spatial cache locality.
💡 5. Production-Ready Embedded Refactoring
Here is an embedded fleet manager using flat contiguous memory with zero pointer indirection:
#include <cstdint> #include <string_view> #include <array> struct DroneTelemetry { char model_name[16]; uint16_t battery_milli_volts; // e.g. 3700 mV uint8_t active_status; }; template <size_t MaxFleetSize> class FlatDroneFleet { private: // Contiguous in SRAM; 100% spatial cache locality; 0 pointer overhead std::array<DroneTelemetry, MaxFleetSize> drones_{}; size_t active_count_{0}; public: bool register_drone(std::string_view model, uint16_t battery_mv) noexcept { if (active_count_ >= MaxFleetSize) return false; DroneTelemetry& d = drones_[active_count_++]; size_t len = model.size() < 15 ? model.size() : 15; for (size_t i = 0; i < len; ++i) d.model_name[i] = model[i]; d.model_name[len] = '\0'; d.battery_milli_volts = battery_mv; d.active_status = 1; return true; } const DroneTelemetry* data() const noexcept { return drones_.data(); } size_t count() const noexcept { return active_count_; } };
📝 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.