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
| Syntax | Description |
|---|---|
| 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 contact us.