Control Flow
2 min read
Control Flow
Control flow determines which code runs and when. C++ provides if/else, switch, and the ternary operator for branching.
if / else if / else
#include <iostream>
int main() {
int score = 75;
if (score >= 90) {
std::cout << "A\n";
} else if (score >= 80) {
std::cout << "B\n";
} else if (score >= 70) {
std::cout << "C\n";
} else {
std::cout << "F\n";
}
}
The condition must be a boolean expression. Any non-zero integer evaluates to true, but relying on this is bad style — write explicit comparisons.
if with initializer (C++17)
You can declare a variable in the if condition. Its scope is limited to the if block:
#include <map>
#include <string>
#include <iostream>
int main() {
std::map<std::string, int> scores = {{"Alice", 95}, {"Bob", 82}};
if (auto it = scores.find("Alice"); it != scores.end()) {
std::cout << "Alice: " << it->second << "\n";
}
// it is not accessible here
}
This pattern avoids leaking the iterator into the surrounding scope.
switch
switch compares one integer or enum value against multiple constants:
#include <iostream>
int main() {
int day = 3;
switch (day) {
case 1: std::cout << "Monday\n"; break;
case 2: std::cout << "Tuesday\n"; break;
case 3: std::cout << "Wednesday\n"; break;
case 4: std::cout << "Thursday\n"; break;
case 5: std::cout << "Friday\n"; break;
default: std::cout << "Weekend\n"; break;
}
}
break exits the switch. Without it, execution falls through to the next case. Fallthrough is occasionally intentional — grouping cases that share a body — but always mark it explicitly to avoid confusion:
switch (cmd) {
case 'q':
case 'Q': // intentional fallthrough
quit();
break;
}
C++17 adds [[fallthrough]] to silence compiler warnings about intentional fallthrough:
case 'q':
[[fallthrough]];
case 'Q':
quit();
break;
Ternary operator
A compact inline conditional:
int x = 10;
std::string label = (x > 0) ? "positive" : "non-positive";
std::cout << label << "\n";
Use it for simple expressions. Avoid nesting ternaries — they become unreadable quickly.
Short-circuit evaluation
Logical operators && and || short-circuit: the right operand is not evaluated if the result is already determined by the left:
int* p = nullptr;
// Safe: p != nullptr is checked first; *p is never read if p is null
if (p != nullptr && *p > 0) {
std::cout << "positive\n";
}
This property is relied on heavily for null pointer checks and condition guards.
Learn modern C++ through working code. Each chapter introduces one concept — variables, functions, classes, templates, smart pointers, concurrency — with a clear example, a line-by-line explanation, and notes on how it applies in real programs.
View book →