11.08 std::sort, std::count_if, and Lambda Inlining vs C qsort Function Pointers
Executive Summary: Exploring the standard algorithm library. We demonstrate why C++ templates and lambdas outperform traditional C
qsort() by enabling complete compiler inlining, and examine stack consumption during recursive algorithms.
💻 1. Annotated Source Code
#include <iostream> #include <cstdlib> #include <ctime> #include <vector> #include <algorithm> using namespace std; void fillVector(vector<int>& myVector); void printVector(const vector<int>& myVector); void countFives(const vector<int>& myVector); int main() { vector<int> myVector; fillVector(myVector); printVector(myVector); countFives(myVector); cout << "\nReplacing 5s with 99s" << endl; replace(myVector.begin(), myVector.end(), 5, 99); countFives(myVector); printVector(myVector); cout << "\nNow sorting vector..." << endl; sort(myVector.begin(), myVector.end()); printVector(myVector); return 0; } void fillVector(vector<int>& myVector) { srand(time(nullptr)); for (int i = 0; i < 20; ++i) { myVector.push_back(rand() % 5 + 1); // 1 to 5 } } void printVector(const vector<int>& myVector) { for (int value : myVector) { cout << value << " "; } } void countFives(const vector<int>& myVector) { int countOfFives = count(myVector.begin(), myVector.end(), 5); cout << "Number of 5s: " << countOfFives << endl; }
📐 2. Architecture & UML Class Model
<<compilation-unit>>
StlAlgorithmsEngine
Generic Algorithm Pipeline
Attributes / Data Members
(none / stateless)
Operations / Methods
+sort<RandomIt>(first: RandomIt, last: RandomIt) : void[IntroSort]
+find_if<InputIt, Pred>(first: InputIt, last: InputIt, p: Pred) : InputIt
+transform<InputIt, OutputIt, Op>(first: InputIt, last: InputIt, d_first: OutputIt, op: Op) : OutputIt
+count_if<InputIt, Pred>(first: InputIt, last: InputIt, p: Pred) : size_t
📚 3. Core C++ Concepts Deep-Dive
1. Decoupled Iterators and Generic Predicates
STL algorithms in <algorithm> operate uniformly on iterator ranges [begin, end) and accept stateless or capturing lambdas as evaluation predicates.
⚡ 4. Embedded Systems & Hardware Reality
1. Zero-Cost Abstraction: Lambdas vs C Function Pointers
In C, qsort() requires a function pointer callback, forcing an indirect call for every comparison. In C++, std::sort accepts a lambda whose type is known at compile time, allowing the compiler to inline the comparison directly into the sort loop for maximum throughput.
💡 5. Production-Ready Embedded Refactoring
💡 Production-Ready Refactor
#include <algorithm> #include <array> #include <iostream> int main() { std::array<int, 5> telemetry = {45, 12, 85, 32, 89}; // Fully inlined at -O2: Zero function pointer overhead std::sort(telemetry.begin(), telemetry.end(), [](int a, int b) { return a < b; }); for (int val : telemetry) std::cout << val << ' '; return 0; }
📝 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 std::sort typically significantly faster than C qsort() on ARM microcontrollers?
Detailed Explanation:
Because
std::sort knows the exact comparator type at compile-time, it inlines the predicate directly, avoiding indirect function pointer jumps.