Last 30 Days
No notifications
Control flow lets your program choose and repeat. C++ inherits all of C's control-flow keywords and adds two modern conveniences: range-based for and if with init.
if / elseint score = 73;
if (score >= 90) cout << "A";
else if (score >= 75) cout << "B";
else if (score >= 60) cout << "C";
else cout << "F";if With Init (C++17)if (auto it = m.find(key); it != m.end()) {
cout << it->second; // it lives only in this if/else
}switchswitch (grade) {
case 'A': cout << "Excellent"; break;
case 'B':
case 'C': cout << "OK"; break; // fall-through
default: cout << "Try again"; break;
}> ⚠️ Don't forget break! Without it, execution falls through to the next case (sometimes intentional, often a bug).
for (int i = 0; i < 5; i++) cout << i; // classic
while (n > 0) n /= 2; // condition first
do { cout << "once"; } while (false); // runs at least oncefor (C++11+)vector<int> nums = {1, 2, 3};
for (int x : nums) cout << x; // copy each element
for (int& x : nums) x *= 2; // modify in place
for (const int& x : nums) cout << x; // read-only, no copy| Keyword | Effect |
break | Exit the innermost loop / switch |
continue | Skip to next iteration |
return | Exit the current function |
goto | (Avoid in modern C++) |
Every algorithm boils down to choose and repeat. C++ gives you a full toolkit and modern C++ keeps adding small, sharp upgrades.
Conditions are anything convertible to bool. Numbers: 0 = false, anything else = true. Pointers: nullptr = false.
if (count) cout << "non-zero";
if (!ptr) cout << "null";
if (s.empty()) cout << "empty string";| Op | Meaning | Short-circuits? | ||
&& | AND | yes — stops on first false | ||
\ | \ | OR | yes — stops on first true | |
! | NOT | – |
if (p != nullptr && p->valid()) // safe — if p is null, p->valid() never runs== != < <= > >= — and <=> (C++20 *spaceship operator*) for three-way comparisons.
> ⚠️ = vs == — if (x = 5) assigns 5 to x and is always true. Most compilers warn about this. Always == in conditions.
if, else, else ifif (cond) {
// ...
} else if (other) {
// ...
} else {
// ...
}Use braces { } even for one-line bodies — saves you from the famous "Apple goto-fail" bug:
if (cond)
doA();
doB(); // ALWAYS runs — not what you might have meantif With Init (C++17)Limit a variable's scope to the if:
if (auto it = map.find(key); it != map.end()) {
use(it->second);
} // 'it' destroyed hereC++20 added the same for switch and for.
int abs = (x < 0) ? -x : x;Great for short choices. Don't nest more than one level — readability dies fast.
switchFor exact-value matches on integers, enums, or characters.
switch (cmd) {
case 'q': quit(); break;
case 'h':
case '?': showHelp(); break; // intentional fall-through
default: cout << "unknown"; break;
}By default, control flows from one matching case into the next until a break. C++17 lets you mark intentional fall-through:
switch (x) {
case 1:
a();
[[fallthrough]]; // tells the compiler "yes, on purpose"
case 2:
b();
break;
}for Loopfor (init; condition; step) {
// body
}for (int i = 0; i < n; ++i) cout << i;
for (int i = n - 1; i >= 0; --i) cout << i; // backwards
for (int i = 0, j = n - 1; i < j; ++i, --j) ; // two cursors++i is conventional in C++. For ints it's identical to i++, but for iterators ++i is sometimes faster (no temporary).
while & do…whilewhile (n > 1) {
if (n % 2 == 0) n /= 2;
else n = 3*n + 1; // Collatz!
}do {
cout << "Try again> ";
cin >> guess;
} while (guess != answer);
Use while when you might do zero iterations; do…while when you need at least one.
for (C++11)The cleanest way to iterate over containers, arrays, strings, anything with begin()/end().
vector<int> v = {1, 2, 3};
for (int x : v) cout << x; // copy each elementfor (int& x : v) x += 10; // modify in place
for (const auto& s : names) cout << s; // big elements: const ref to avoid copies
Pattern: auto& to modify, const auto& to read.
break & continuefor (int x : nums) {
if (x < 0) continue; // skip negatives
if (x == 0) break; // stop at first zero
cout << x << ' ';
}C++ has no labelled break. Common idioms:
bool done = false;
for (int i = 0; i < n && !done; ++i)
for (int j = 0; j < n; ++j)
if (grid[i][j] == target) { done = true; break; }Or just put it in a function and use return. Cleaner.
goto?C++ has goto. Don't use it for normal flow. The one defensible use is jumping to a single cleanup label in deeply nested C-style code — and even then, RAII is better.
| Bug | Cause | |||
Off-by-one (<= instead of <) | Loop runs one extra time | |||
Forgot break in switch | Unintended fall-through | |||
if (x = 5) | Assignment instead of comparison | |||
| Modifying a container while iterating | Iterator invalidation | Cheat-Sheet | Need | Idiom |
| Pick one of many | if/else if/else | |||
| Match exact value | switch | |||
| Run N times | for (int i = 0; i < N; ++i) | |||
| Until condition | while (cond) | |||
| At least once | do { ... } while (cond); | |||
| Iterate container | for (const auto& x : v) | |||
| Modify in place | for (auto& x : v) | |||
| Skip iteration | continue | |||
| Stop loop | break | |||
| Exit function | return |
Master these and you can express any algorithm. The next phase introduces functions — a way to package the control flow you write here.