for
loop
Conditionally executes a statement repeatedly, where the statement does not need to manage the loop condition.
Syntax
attr (optional) for ( init-statement condition (optional) ; expression (optional) ) statement
|
|||||||||
attr | - | (since C++11) any number of attributes | ||
init-statement | - | one of
Note that any init-statement must end with a semicolon. This is why it is often described informally as an expression or a declaration followed by a semicolon. | ||
condition | - | a condition | ||
expression | - | an expression (typically an expression that increments the loop counter) | ||
statement | - | a statement (typically a compound statement) |
Condition
A condition can either be an expression or a simple declaration.
|
(since C++26) |
- If it can be syntactically resolved as an expression, it is treated as an expression. Otherwise, it is treated as a declaration that is not a structured binding declaration(since C++26).
When control reaches condition, the condition will yield a value, which is used to determine whether statement will be executed.
Expression
If condition is an expression, the value it yields is the the value of the expression contextually converted to bool. If that conversion is ill-formed, the program is ill-formed.
Declaration
If condition is a simple declaration, the value it yields is the value of the decision variable (see below) contextually converted to bool. If that conversion is ill-formed, the program is ill-formed.
Non-structured binding declaration
The declaration has the following restrictions:
- Syntactically conforms to the following form:
|
(until C++11) |
|
(since C++11) |
- The declarator cannot specify a function or an array.
- The type specifier sequence(until C++11)declaration specifier sequence can only contain type specifiers and constexpr, and it(since C++11) cannot define a class or enumeration.
The decision varaiable of the declaration is the declared variable.
Structured binding declarationThe declaration has the following restrictions:
The decision variable of the declaration is the invented variable e introduced by the declaration. |
(since C++26) |
Explanation
A for statement equivalent to:
{
|
|||||||||
Except that
- The scope of init-statement and the scope of condition are the same.
- The scope of statement and the scope of expression are disjoint and nested within the scope of init-statement and condition.
- Executing a continue statement in statement will evaluate expression.
- Empty condition is equivalent to true.
If the loop needs to be terminated within statement, a break statement can be used as terminating statement.
If the current iteration needs to be terminated within statement, a continue statement can be used as shortcut.
Notes
As is the case with while
loop, if statement is not a compound statement, the scope of variables declared in it is limited to the loop body as if it was a compound statement.
for (;;) int n; // n goes out of scope
As part of the C++ forward progress guarantee, the behavior is undefined if a loop that is not a trivial infinite loop(since C++26) without observable behavior does not terminate. Compilers are permitted to remove such loops.
While in C names declared in the scope of init-statement and condition can be shadowed in the scope of statement, it is forbidden in C++:
for (int i = 0;;) { long i = 1; // valid C, invalid C++ // ... }
Keywords
Example
#include <iostream> #include <vector> int main() { std::cout << "1) typical loop with a single statement as the body:\n"; for (int i = 0; i < 10; ++i) std::cout << i << ' '; std::cout << "\n\n" "2) init-statement can declare multiple names, as\n" "long as they can use the same decl-specifier-seq:\n"; for (int i = 0, *p = &i; i < 9; i += 2) std::cout << i << ':' << *p << ' '; std::cout << "\n\n" "3) condition may be a declaration:\n"; char cstr[] = "Hello"; for (int n = 0; char c = cstr[n]; ++n) std::cout << c; std::cout << "\n\n" "4) init-statement can use the auto type specifier:\n"; std::vector<int> v = {3, 1, 4, 1, 5, 9}; for (auto iter = v.begin(); iter != v.end(); ++iter) std::cout << *iter << ' '; std::cout << "\n\n" "5) init-statement can be an expression:\n"; int n = 0; for (std::cout << "Loop start\n"; std::cout << "Loop test\n"; std::cout << "Iteration " << ++n << '\n') { if (n > 1) break; } std::cout << "\n" "6) constructors and destructors of objects created\n" "in the loop's body are called per each iteration:\n"; struct S { S(int x, int y) { std::cout << "S::S(" << x << ", " << y << "); "; } ~S() { std::cout << "S::~S()\n"; } }; for (int i{0}, j{5}; i < j; ++i, --j) S s{i, j}; std::cout << "\n" "7) init-statement can use structured bindings:\n"; long arr[]{1, 3, 7}; for (auto [i, j, k] = arr; i + j < k; ++i) std::cout << i + j << ' '; std::cout << '\n'; }
Output:
1) typical loop with a single statement as the body: 0 1 2 3 4 5 6 7 8 9 2) init-statement can declare multiple names, as long as they can use the same decl-specifier-seq: 0:0 2:2 4:4 6:6 8:8 3) condition may be a declaration: Hello 4) init-statement can use the auto type specifier: 3 1 4 1 5 9 5) init-statement can be an expression: Loop start Loop test Iteration 1 Loop test Iteration 2 Loop test 6) constructors and destructors of objects created in the loop's body are called per each iteration: S::S(0, 5); S::~S() S::S(1, 4); S::~S() S::S(2, 3); S::~S() 7) init-statement can use structured bindings: 4 5 6
See also
range-for loop(C++11)
|
executes loop over range |
C documentation for for
|