Skip to content

Loops — for, while, do-while, Range-Based for, break, continue

DodaTech Updated 2026-06-28 8 min read

In this tutorial, you will learn about Loops. We cover key concepts, practical examples, and best practices to help you master this topic.

C++ offers four loop constructs — for, while, do-while, and range-based for — each suited to different iteration patterns and all supporting break and continue for fine-grained control.

What You'll Learn

You will understand when to use each loop type, master the range-based for loop introduced in C++11 (with C++20 extensions), control loop flow with break and continue, avoid infinite loops and off-by-one errors, and see how loops interact with containers and iterators.

Why It Matters

Loops are the fundamental mechanism for processing sequences of data. Every non-trivial program iterates over collections, processes input streams, or repeats operations until a condition is met. Choosing the right loop type and understanding its semantics separates clean, correct code from buggy, hard-to-maintain code.

Learning Path

graph LR
    A["07: Control Flow"] --> B["08: Loops"]
    B --> C["09: Arrays & C-Strings"]
    C --> D["10: Functions"]
    style A fill:#4a90d9,stroke:#2c5f8a,color:#fff
    style B fill:#4a90d9,stroke:#2c5f8a,color:#fff
    style C fill:#4a90d9,stroke:#2c5f8a,color:#fff
    style D fill:#4a90d9,stroke:#2c5f8a,color:#fff

The for Loop

The classic for loop has three parts: initialization, condition, and increment.

#include <iostream>

int main() {
    for (int i = 0; i < 5; ++i) {
        std::cout << i << " ";
    }
    std::cout << "\n";
    // Output: 0 1 2 3 4
    
    // Multiple variables
    for (int i = 0, j = 10; i < j; ++i, --j) {
        std::cout << i << "-" << j << " ";
    }
    std::cout << "\n";
    // Output: 0-10 1-9 2-8 3-7 4-6
    
    // Omitted sections
    int k = 0;
    for (; k < 3; ) {
        std::cout << k++ << " ";
    }
    std::cout << "\n";
    // Output: 0 1 2
    
    // Infinite loop (use Ctrl+C to stop)
    // for (;;) { std::cout << "forever "; }
}

The three sections of for are optional. A missing condition defaults to true. You can declare multiple variables of the same type in the initialization section.

The while Loop

A while loop checks the condition before each iteration. It runs zero or more times.

#include <iostream>

int main() {
    int i = 0;
    while (i < 5) {
        std::cout << i << " ";
        ++i;
    }
    std::cout << "\n";
    // Output: 0 1 2 3 4
    
    // Sentinel-controlled loop
    int sum = 0;
    int value;
    std::cout << "Enter numbers (negative to stop): ";
    while (std::cin >> value && value >= 0) {
        sum += value;
    }
    std::cout << "Sum: " << sum << "\n";
    
    // Boolean flag
    bool found = false;
    int numbers[] = {3, 7, 1, 9, 4};
    int idx = 0;
    while (!found && idx < 5) {
        if (numbers[idx] == 9) found = true;
        else ++idx;
    }
    std::cout << "9 found at index " << idx << "\n";
}

The do-while Loop

A do-while loop checks the condition after each iteration. It always executes at least once.

#include <iostream>

int main() {
    int i = 0;
    do {
        std::cout << i << " ";
        ++i;
    } while (i < 5);
    std::cout << "\n";
    // Output: 0 1 2 3 4
    
    // Guaranteed at least one execution
    int x = 10;
    do {
        std::cout << "runs once\n";
    } while (x < 5);
    // Output: runs once
    
    // Menu-driven program pattern
    char choice;
    do {
        std::cout << "Menu: (q)uit, (h)ello: ";
        std::cin >> choice;
        if (choice == 'h') std::cout << "Hello!\n";
    } while (choice != 'q');
}

The do-while is ideal for menus and input validation where you need to show the prompt at least once.

Range-Based for Loop (C++11)

The range-based for loop iterates over every element in a container or array.

#include <iostream>
#include <vector>

int main() {
    int arr[] = {10, 20, 30, 40, 50};
    
    for (int x : arr) {
        std::cout << x << " ";
    }
    std::cout << "\n";
    // Output: 10 20 30 40 50
    
    std::vector<std::string> names = {"Alice", "Bob", "Charlie"};
    for (const std::string& name : names) {
        std::cout << name << " ";
    }
    std::cout << "\n";
    // Output: Alice Bob Charlie
    
    // Modify elements with reference
    for (int& x : arr) {
        x *= 2;
    }
    for (int x : arr) {
        std::cout << x << " ";
    }
    std::cout << "\n";
    // Output: 20 40 60 80 100
    
    // C++20: range-based for with initializer
    for (std::vector<int> vec = {1, 2, 3}; int v : vec) {
        std::cout << v << " ";
    }
    std::cout << "\n";
}

Always use const auto& for read-only iteration of non-trivial types, auto& to modify elements, and auto for cheap-to-copy types (int, char, bool, pointers).

break and continue

#include <iostream>

int main() {
    // break: exit the loop immediately
    for (int i = 0; i < 10; ++i) {
        if (i == 5) break;
        std::cout << i << " ";
    }
    std::cout << "\n";
    // Output: 0 1 2 3 4
    
    // continue: skip to next iteration
    for (int i = 0; i < 10; ++i) {
        if (i % 2 == 0) continue;
        std::cout << i << " ";
    }
    std::cout << "\n";
    // Output: 1 3 5 7 9
    
    // Nested loop with break (breaks only the inner loop)
    for (int i = 0; i < 3; ++i) {
        for (int j = 0; j < 3; ++j) {
            if (j == 1) break;
            std::cout << i << "," << j << " ";
        }
    }
    std::cout << "\n";
    // Output: 0,0 1,0 2,0
}

break exits the innermost enclosing loop. continue skips the rest of the current iteration and evaluates the loop condition again.

Loop Comparison

Loop When the Condition is Checked Minimum Executions Best Use Case
for Before each iteration 0 Known number of iterations, counter-controlled
while Before each iteration 0 Condition-controlled, unknown iterations
do-while After each iteration 1 Menu-driven, input validation
Range-for N/A (uses iterators) 0 Iterating over containers/arrays

Common Mistakes

Mistake 1: Off-by-One Errors

int arr[5];
for (int i = 0; i <= 5; ++i) arr[i] = i;  // writes to arr[5], out of bounds

Use strict less-than (<) for zero-based indexing.

Mistake 2: Infinite Loops

for (int i = 0; i < 10; ++j) { ... }  // i never increments

Double-check that your loop variable actually changes toward the exit condition.

Mistake 3: Modifying Container During Range-For

std::vector<int> v = {1, 2, 3};
for (int x : v) {
    v.push_back(x);  // invalidates iterators, undefined behavior
}

Do not add or remove elements from a container while iterating with range-for.

Mistake 4: continue in While Skips Increment

int i = 0;
while (i < 10) {
    if (i % 2 == 0) continue;  // skips ++i, infinite loop!
    ++i;
}

In a while loop, continue jumps to the condition check, skipping any increment below it. Use for loops to avoid this pattern.

Mistake 5: Forgetting Semicolon After do-while

do {
    std::cout << "hello\n";
} while (false)  // Error: missing semicolon

Mistake 6: Using = Instead of == in Condition

while (int i = 10) { ... }  // assigns 10, always true

Practice Questions

  1. What is the difference between while and do-while?
  2. Write a range-based for loop that doubles every element in an std::vector<int>.
  3. What does break do inside a nested loop?
  4. Write a loop that prints the first 10 Fibonacci numbers.
  5. Convert this while loop to a for loop: int i = 0; while (i < 10) { cout << i; ++i; }

Challenge

Write a program that reads integers from std::cin until a negative number is entered, stores them in a std::vector<int>, then prints only the even numbers using a range-based for loop with continue.

FAQ

Can I use `break` inside a range-based for loop?

Yes. break works inside any loop construct to exit immediately.

What is the performance difference between loop types?

Modern compilers optimize all loop types to equivalent machine code for simple cases. Choose the loop type that best expresses the intent.

Why does range-based for not give me the index?

Range-based for focuses on the element, not the index. If you need the index, use a traditional for loop with a counter, or use zip views (C++23).

Can I iterate backwards with range-based for?

Not directly. Use std::ranges::reverse_view (C++20) or a traditional for loop with --i.

Is `while (true)` acceptable?

Yes, as long as there is an explicit break somewhere in the loop. It is a common pattern for event loops and server main loops.

What is the difference between `for (auto x : v)` and `for (auto& x : v)`?

The first copies each element (expensive for large types). The second gives a reference without copying. Use auto& for non-trivial types.

Mini Project

Write a prime number generator:

#include <iostream>
#include <vector>

bool isPrime(int n) {
    if (n < 2) return false;
    for (int d = 2; d * d <= n; ++d) {
        if (n % d == 0) return false;
    }
    return true;
}

int main() {
    std::vector<int> primes;
    
    for (int i = 2; i <= 100; ++i) {
        if (isPrime(i)) {
            primes.push_back(i);
        }
    }
    
    std::cout << "Primes up to 100:\n";
    for (int p : primes) {
        std::cout << p << " ";
    }
    std::cout << "\nCount: " << primes.size() << "\n";
}

Expected output:

Primes up to 100:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
Count: 25

What's Next

Loops let you Process sequences of data efficiently. The next lesson covers C-style arrays and C-strings, including array decay, pointer arithmetic, and the std::array fixed-size container.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro