C++ Cheatsheet
Control Flow
Use this C++ reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.
if / else
if (x > 0) { // ... } else if (x < 0) { // ... } else { // ... } // Single-statement (braces optional but recommended) if (x > 0) doSomething(); // if with initializer (C++17) if (int n = compute(); n > 0) { use(n); // n is in scope here and in else } else { handle(n); } // Constexpr if — branch chosen at compile time (C++17) template<typename T> void process(T val) { if constexpr (std::is_integral_v<T>) { // only compiled when T is integral } else { // only compiled otherwise } }
switch
switch (expr) { // expr must be integral or enum case 1: doA(); break; // without break, falls through to next case case 2: case 3: // multiple cases share one body doBC(); break; case 4: doD(); [[fallthrough]]; // C++17: explicit intentional fallthrough (silences warning) case 5: doDE(); break; default: doDefault(); break; // good practice even in default } // switch with initializer (C++17) switch (auto ch = getChar(); ch) { case 'a': /* ... */ break; default: /* ... */ }
Variables cannot be declared between cases without a block:
case 2: { int x = 5; // OK inside a block break; }
while Loop
while (condition) { // body — runs as long as condition is true // condition checked BEFORE each iteration } int i = 0; while (i < 10) { std::cout << i << " "; ++i; } // Infinite loop while (true) { if (done) break; }
do-while Loop
do { // body always runs at least once // condition checked AFTER each iteration } while (condition); int choice; do { std::cout << "Enter 1-3: "; std::cin >> choice; } while (choice < 1 || choice > 3);
for Loop
// Classic for for (init; condition; increment) { body } for (int i = 0; i < n; ++i) { /* i = 0, 1, ..., n-1 */ } for (int i = n - 1; i >= 0; --i) { /* reverse */ } for (int i = 0, j = n - 1; i < j; ++i, --j) { /* two vars */ } // Infinite loop for (;;) { if (done) break; } // Range-based for (C++11) std::vector<int> v = {1, 2, 3}; for (int x : v) { /* copy */ } for (int& x : v) { x *= 2; /* modify in place */ } for (const int& x : v) { /* read-only, no copy */ } for (auto x : v) { /* deduce type */ } for (auto [key, val] : myMap) { /* structured binding, C++17 */ } // Range-based for with initializer (C++20) for (auto&& v = getVec(); auto x : v) { use(x); } // auto&& binds the rvalue
break, continue, goto
// break — exit the innermost loop or switch for (int i = 0; i < 10; ++i) { if (i == 5) break; // stops at 5 } // continue — skip the rest of the current iteration for (int i = 0; i < 10; ++i) { if (i % 2 == 0) continue; // skip even process(i); } // goto — jump to label (avoid; useful only for breaking nested loops) for (int i = 0; i < 10; ++i) { for (int j = 0; j < 10; ++j) { if (bad(i, j)) goto done; } } done: // continues here
Ternary Operator
int abs_x = (x >= 0) ? x : -x; // Chained (readable only for two levels) std::string grade = (score >= 90) ? "A" : (score >= 80) ? "B" : (score >= 70) ? "C" : "F"; // Can be used where a value is required (unlike if) std::cout << (x > 0 ? "positive" : "non-positive") << "\n";
std::optional as a Control Flow Tool (C++17)
#include <optional> std::optional<int> find(int key) { if (/* found */) return 42; return std::nullopt; } if (auto result = find(key)) { use(*result); // dereference }
Structured Bindings (C++17)
#include <tuple> #include <map> auto [a, b] = std::pair{1, 2.0}; // a=int, b=double auto [x, y, z] = std::tuple{1, 2, 3}; std::map<std::string, int> m = {{"a", 1}}; for (auto& [key, val] : m) { std::cout << key << "=" << val << "\n"; } // Ignoring elements (no official discard, use _) auto [first, _] = std::pair{1, 99}; // some compilers warn on duplicate _
Early Return Pattern
// Prefer returning early over deep nesting int process(int x) { if (x < 0) return -1; // guard clause if (x == 0) return 0; return x * 2; }
Loops Over Containers — Patterns
#include <vector> #include <algorithm> std::vector<int> v = {3, 1, 4, 1, 5}; // Index-based (when index matters) for (std::size_t i = 0; i < v.size(); ++i) { v[i] *= 2; } // Iterator-based for (auto it = v.begin(); it != v.end(); ++it) { *it *= 2; } // Range-for (preferred) for (auto& x : v) { x *= 2; } // Algorithm (see STL Algorithms) std::for_each(v.begin(), v.end(), [](int& x){ x *= 2; });
Jump Table Alternative with Arrays
// Replace long switch on sequential ints with a function table using Fn = void(*)(); Fn table[] = { funcA, funcB, funcC }; if (cmd < 3) table[cmd]();
Assertions
#include <cassert> assert(x > 0); // aborts if false in debug builds // disabled when NDEBUG is defined (release builds) // C++11: static_assert (compile-time) static_assert(sizeof(int) == 4, "Expected 32-bit int"); static_assert(std::is_trivial_v<MyStruct>); // no message required (C++17)