Skip to main content

for and range-based for

beginner11 min readLesson 13 of 204

Counting loops, the off-by-one discipline, and the range-based for you will use for everything else.

Counting: the classic for

for (int i = 1; i <= 5; ++i) {
    std::cout << i << ' ';
}
// prints: 1 2 3 4 5

Three parts: initialize (int i = 1), condition (i <= 5, checked before each pass), step (++i, after each pass). Prefer ++i over i++ as a style habit (never slower, occasionally faster).

Off-by-one discipline

Counting 1..N uses i = 1; i <= N. Indexing positions 0..N-1 uses i = 0; i < N. Mixing the two habits produces the classic off-by-one bug: one extra or one missing iteration. Decide why you are looping, then pick the shape deliberately.

Range-based for โ€” the modern default

#include <vector>
#include <string>

std::vector<int> scores{9, 7, 10};

for (int s : scores) {          // one pass, no index bookkeeping
    std::cout << s << ' ';
}

for (const auto& name : names) { // const& = read-only, no copy (module 11 explains &)
    std::cout << name << '\n';
}

Use range-for whenever you just visit every element โ€” it cannot run off the end. Use the classic for when you need the index (positions, strides, two-at-a-time).

break and continue

break exits the loop now; continue skips to the next iteration. Use them to keep the happy path unindented:

for (const auto& line : lines) {
    if (line.empty() || line[0] == '#') continue;  // skip noise
    if (line == "STOP") break;                     // early exit
    process(line);
}

Now practice

Loop Practice: Shapes and SumsTriangles, multiplication table, FizzBuzz's serious cousin, and a sum-with-skip.1 challenge ยท ยท ~25 min