⚡C++AdvancedLesson 50 of 50CamboFreelanceJune 19, 2026
C++ Performance Optimization
Complete your C++ journey with performance optimization: profiling, cache-friendly code, avoiding copies, vector reserve, and compiler flags.
Advanced12 min readLesson 50 of 50
Why Optimize?
C++ is chosen for performance-critical applications. Understanding where time is spent — and how to reduce it — is the final skill in mastering C++.
Step 1 — Profile Before Optimizing
// Measure execution time using chrono
#include <chrono>
using namespace std::chrono;
auto start = high_resolution_clock::now();
// ... code to measure ...
auto end = high_resolution_clock::now();
auto ms = duration_cast<milliseconds>(end - start).count();
cout << "Elapsed: " << ms << "ms" << endl;
Use profiling tools: gprof, perf (Linux), Instruments (macOS), VTune (Intel).
Cache-Friendly Code
Modern CPUs are much faster than RAM. Access memory sequentially (row-major) to leverage the cache:
const int N = 1000;
int matrix[N][N];
// Slow — column-major, many cache misses
for (int j = 0; j < N; j++)
for (int i = 0; i < N; i++)
matrix[i][j] = 0;
// Fast — row-major, cache-friendly
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
matrix[i][j] = 0;
Avoid Unnecessary Copies
// Bad — copies string
void process(string s) { ... }
// Good — no copy
void process(const string& s) { ... }
// Best for rvalues — steal the string
void process(string&& s) { data = move(s); }
Reserve Vector Capacity
vector<int> v;
v.reserve(1000000); // pre-allocate — avoids repeated reallocations
for (int i = 0; i < 1000000; i++) v.push_back(i);
Compiler Optimizations
Flag
Level
-O0
No optimization (debug)
-O1
Basic optimizations
-O2
Moderate (recommended release)
-O3
Aggressive (may increase binary size)
-Ofast
O3 + allow floating-point shortcuts
Key Optimization Tips
Prefer emplace_back over push_back to construct in-place.
Use unordered_map instead of map for O(1) avg lookups.
Avoid dynamic allocation in hot loops — allocate once, reuse.
Use const& for read-only parameters of non-trivial types.
Enable Link Time Optimization: -flto.
Mark hot functions inline or __attribute__((hot)).
Final Exercise
Benchmark two approaches to summing 10 million integers: (1) using a plain C array; (2) using a vector with reserve(). Measure and compare the time using chrono.
Show Solution
#include <iostream>
#include <vector>
#include <chrono>
#include <numeric>
using namespace std;
using namespace chrono;
int main() {
const int N = 10000000;
// Array approach
auto t1 = high_resolution_clock::now();
long long sum1 = 0;
int* arr = new int[N];
for (int i = 0; i < N; i++) arr[i] = i;
for (int i = 0; i < N; i++) sum1 += arr[i];
delete[] arr;
auto t2 = high_resolution_clock::now();
cout << "Array sum: " << sum1 << " in " << duration_cast<milliseconds>(t2-t1).count() << "ms\n";
// Vector approach
auto t3 = high_resolution_clock::now();
vector<int> v; v.reserve(N);
for (int i = 0; i < N; i++) v.push_back(i);
long long sum2 = accumulate(v.begin(), v.end(), 0LL);
auto t4 = high_resolution_clock::now();
cout << "Vector sum: " << sum2 << " in " << duration_cast<milliseconds>(t4-t3).count() << "ms\n";
return 0;
}
Quiz
Why is row-major iteration faster than column-major for 2D arrays?
A) Row-major uses less memory
B> Column-major triggers more cache misses because memory is accessed non-sequentially
C) Row-major uses fewer loops
D> The compiler automatically converts column-major
Answer
B) C++ stores 2D arrays in row-major order. Column-major access skips over cache lines, causing frequent cache misses and slowdowns.
Summary & Congratulations!
You have completed the full C++ Tutorial Series — from Hello World to performance optimization!
Profile first — optimize the bottleneck, not random code.