Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

  1. Home
  2. C++ Dictionary
  3. for / Range-based for Loop

for / Range-based for Loop

C++ has two types of for loops: the traditional three-clause for loop and the range-based for statement that directly iterates over container elements. This page uses Steins;Gate lab member data to demonstrate both styles, along with reverse loops, nested loops, and continue / break control.

Syntax

// ========================================
// Basic for loop syntax
// ========================================

// for (init; condition; update) { body }
for (int i = 0; i < 10; i++) {
    // Repeats while i is 0 through 9
}

// ========================================
// Range-based for syntax
// ========================================

// for (type var : container) { body }
// auto deduces the type automatically
for (auto& element : container) {
    // Process each element in the container in order
}

// const reference: avoids copy and prevents modification
for (const auto& element : container) {
    // Process each element read-only
}

// ========================================
// Reverse loop syntax
// ========================================

// Start from the last index and count down
for (int i = static_cast<int>(vec.size()) - 1; i >= 0; i--) {
    // Process from the last element toward the first
}

// ========================================
// Nested for loop syntax
// ========================================

for (int i = 0; i < rows; i++) {
    for (int j = 0; j < cols; j++) {
        // Process element at row i, column j
    }
}

Syntax Reference

SyntaxDescription
for (init; cond; update) { }Traditional three-clause for loop. Controls iteration count with a counter variable.
for (auto x : container) { }Range-based for statement. Iterates from the beginning to the end of the container, copying each element.
for (auto& x : container) { }Range-based for with reference. Avoids copy and allows direct modification of elements.
for (const auto& x : container) { }Range-based for with const reference. Avoids copy while making elements read-only.
continue;Skips the remainder of the current iteration and proceeds to the next loop cycle.
break;Immediately exits the loop and jumps to the code after the for block.
for (int i = n-1; i >= 0; i--) { }Reverse loop. Counts down from the last index toward the first.
for (…) { for (…) { } }Nested for loop. Used for multi-dimensional structures or Cartesian products.

Sample Code

for_loop.cpp
// ========================================
// for_loop.cpp — for loop sample
// Uses Steins;Gate lab member data to
// demonstrate basic for, range-based for,
// reverse loop, and nested loops
// ========================================

#include <iostream>
#include <string>
#include <vector>

int main() {
    std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 8};
    std::vector<std::string> names = {
        "Hououin Kyouma",    // NO.001
        "Shiina Mayuri",     // NO.002
        "Hashida Itaru",     // NO.003
        "Makise Kurisu",     // NO.004
        "Kiryu Moeka",       // NO.005
        "Urushibara Ruka",   // NO.006
        "Amane Suzuha",      // NO.008 (NO.007 is vacant)
    };

    // Basic for loop
    std::cout << "=== Basic for loop ===" << std::endl;
    for (int i = 0; i < static_cast<int>(names.size()); i++) {
        std::cout << "Lab member NO." << numbers[i] << ": " << names[i] << std::endl;
    }

    // Range-based for (const reference)
    std::cout << "\n=== Range-based for ===" << std::endl;
    for (const auto& name : names) {
        std::cout << name << std::endl;
    }

    // continue: skip NO.004 and beyond
    std::cout << "\n=== continue (skip NO.004 and above) ===" << std::endl;
    for (int i = 0; i < static_cast<int>(names.size()); i++) {
        if (numbers[i] >= 4) { continue; }
        std::cout << "Lab member NO." << numbers[i] << ": " << names[i] << std::endl;
    }

    // break: stop when Hashida is found
    std::cout << "\n=== break (search for Hashida and stop) ===" << std::endl;
    for (const auto& name : names) {
        std::cout << "Checking: " << name << std::endl;
        if (name == "Hashida Itaru") {
            std::cout << "→ Hashida Itaru found. Exiting loop." << std::endl;
            break;
        }
    }

    // Reverse loop
    std::cout << "\n=== Reverse loop ===" << std::endl;
    for (int i = static_cast<int>(names.size()) - 1; i >= 0; i--) {
        std::cout << "Lab member NO." << numbers[i] << ": " << names[i] << std::endl;
    }

    // Nested for: pairs of lab members
    std::cout << "\n=== Nested for (pairs) ===" << std::endl;
    for (int i = 0; i < 3; i++) {
        for (int j = i + 1; j < 3; j++) {
            std::cout << names[i] << " & " << names[j] << std::endl;
        }
    }

    return 0;
}
g++ -std=c++17 for_loop.cpp -o for_loop
./for_loop
=== Basic for loop ===
Lab member NO.1: Hououin Kyouma
Lab member NO.2: Shiina Mayuri
Lab member NO.3: Hashida Itaru
Lab member NO.4: Makise Kurisu
Lab member NO.5: Kiryu Moeka
Lab member NO.6: Urushibara Ruka
Lab member NO.8: Amane Suzuha

=== Range-based for ===
Hououin Kyouma
Shiina Mayuri
Hashida Itaru
Makise Kurisu
Kiryu Moeka
Urushibara Ruka
Amane Suzuha

=== continue (skip NO.004 and above) ===
Lab member NO.1: Hououin Kyouma
Lab member NO.2: Shiina Mayuri
Lab member NO.3: Hashida Itaru

=== break (search for Hashida and stop) ===
Checking: Hououin Kyouma
Checking: Shiina Mayuri
Checking: Hashida Itaru
→ Hashida Itaru found. Exiting loop.

=== Reverse loop ===
Lab member NO.8: Amane Suzuha
Lab member NO.6: Urushibara Ruka
Lab member NO.5: Kiryu Moeka
Lab member NO.4: Makise Kurisu
Lab member NO.3: Hashida Itaru
Lab member NO.2: Shiina Mayuri
Lab member NO.1: Hououin Kyouma

=== Nested for (pairs) ===
Hououin Kyouma & Shiina Mayuri
Hououin Kyouma & Hashida Itaru
Shiina Mayuri & Hashida Itaru

Common Mistake 1: Signed/unsigned comparison warning with size_t

The return type of vector::size() is an unsigned integer (size_t). Comparing it with a signed integer (int) counter generates a compiler warning. Additionally, using size_t directly in a reverse loop causes an unsigned integer underflow when it wraps below zero.

// NG: Reverse loop with size_t can underflow
std::vector<std::string> names = { "Hououin Kyouma", "Shiina Mayuri", "Makise Kurisu" };
for (size_t i = names.size() - 1; i >= 0; i--) {  // When i is 0, decrement wraps to max value
    std::cout << names[i] << std::endl;
}

OK: Explicitly cast to int before using in the loop.

// OK: Cast to int with static_cast first
std::vector<std::string> names = { "Hououin Kyouma", "Shiina Mayuri", "Makise Kurisu" };
for (int i = static_cast<int>(names.size()) - 1; i >= 0; i--) {
    std::cout << names[i] << std::endl;
}
g++ -std=c++17 reverse_loop.cpp -o reverse_loop
./reverse_loop
Makise Kurisu
Shiina Mayuri
Hououin Kyouma

Common Mistake 2: Modifying the container during a range-based for

Adding or removing elements from a container while iterating over it with a range-based for invalidates the iterator and causes undefined behavior.

// NG: Modifying a vector during range-based for
std::vector<std::string> names = { "Hououin Kyouma", "Shiina Mayuri" };
for (const auto& name : names) {
    names.push_back("Makise Kurisu");  // Iterator invalidated — undefined behavior
}

OK: Iterate over a copy of the container.

// OK: Iterate over a copy
std::vector<std::string> names = { "Hououin Kyouma", "Shiina Mayuri" };
std::vector<std::string> copy = names;
for (const auto& name : copy) {
    names.push_back(name + " (copy)");
}
g++ -std=c++17 for_safe.cpp -o for_safe
./for_safe
names element count: 4

Overview

The traditional for loop is controlled with the three-clause for (init; condition; update) form. It is particularly useful for fine-grained control such as referencing multiple containers by index simultaneously or counting down in reverse. The range-based for statement is written as for (const auto& x : container) and allows iterating over all elements without managing an index. Using const auto& when elements are not modified, and auto& when modification is needed, is a commonly used pattern. continue skips the remaining processing in the current iteration and proceeds to the next loop, while break immediately exits the entire loop. Nested for loops are used for matrix traversal or Cartesian products, and for deep nesting, extracting inner loops into functions is one approach to consider.

If you find any errors or copyright issues, please .