Iteration statements specify looping.
iteration-statement: while ( condition ) statement do statement while ( expression ) ; for ( for-init-statement conditionopt ; expressionopt ) statement for ( for-range-declaration : for-range-initializer ) statement
for-init-statement: expression-statement simple-declaration
for-range-declaration: attribute-specifier-seqopt decl-specifier-seq declarator
for-range-initializer: expression braced-init-list
See [dcl.meaning] for the optional attribute-specifier-seq in a for-range-declaration. [ Note: A for-init-statement ends with a semicolon. — end note ]
The substatement in an iteration-statement implicitly defines a block scope ([basic.scope]) which is entered and exited each time through the loop.
If the substatement in an iteration-statement is a single statement and not a compound-statement, it is as if it was rewritten to be a compound-statement containing the original statement. [ Example:
while (--x >= 0) int i;
can be equivalently rewritten as
while (--x >= 0) { int i; }
Thus after the while statement, i is no longer in scope. — end example ]
[ Note: The requirements on conditions in iteration statements are described in [stmt.select]. — end note ]
In the while statement the substatement is executed repeatedly until the value of the condition ([stmt.select]) becomes false. The test takes place before each execution of the substatement.
When the condition of a while statement is a declaration, the scope of the variable that is declared extends from its point of declaration ([basic.scope.pdecl]) to the end of the while statement. A while statement of the form
while (T t = x) statement
is equivalent to
label:{ // start of condition scope T t = x; if (t) { statement goto label; } } // end of condition scope
The variable created in a condition is destroyed and created with each iteration of the loop. [ Example:
struct A {
int val;
A(int i) : val(i) { }
~A() { }
operator bool() { return val != 0; }
};
int i = 1;
while (A a = i) {
// ...
i = 0;
}
In the while-loop, the constructor and destructor are each called twice, once for the condition that succeeds and once for the condition that fails. — end example ]
The expression is contextually converted to bool (Clause [conv]); if that conversion is ill-formed, the program is ill-formed.
In the do statement the substatement is executed repeatedly until the value of the expression becomes false. The test takes place after each execution of the statement.
The for statement
for ( for-init-statement conditionopt ; expressionopt ) statement
is equivalent to
{ for-init-statement while ( condition ) { statement expression ; } }
except that names declared in the for-init-statement are in the same declarative-region as those declared in the condition, and except that a continue in statement (not enclosed in another iteration statement) will execute expression before re-evaluating condition. [ Note: Thus the first statement specifies initialization for the loop; the condition ([stmt.select]) specifies a test, made before each iteration, such that the loop is exited when the condition becomes false; the expression often specifies incrementing that is done after each iteration. — end note ]
Either or both of the condition and the expression can be omitted. A missing condition makes the implied while Clause equivalent to while(true).
If the for-init-statement is a declaration, the scope of the name(s) declared extends to the end of the for-statement. [ Example:
int i = 42;
int a[10];
for (int i = 0; i < 10; i++)
a[i] = i;
int j = i; // j = 42
— end example ]
For a range-based for statement of the form
for ( for-range-declaration : expression ) statement
let range-init be equivalent to the expression surrounded by parentheses86
( expression )
and for a range-based for statement of the form
for ( for-range-declaration : braced-init-list ) statement
let range-init be equivalent to the braced-init-list. In each case, a range-based for statement is equivalent to
{ auto && __range = range-init; for ( auto __begin = begin-expr, __end = end-expr; __begin != __end; ++__begin ) { for-range-declaration = *__begin; statement } }
where __range, __begin, and __end are variables defined for exposition only, and _RangeT is the type of the expression, and begin-expr and end-expr are determined as follows:
if _RangeT is an array type, begin-expr and end-expr are __range and __range + __bound, respectively, where __bound is the array bound. If _RangeT is an array of unknown size or an array of incomplete type, the program is ill-formed;
if _RangeT is a class type, the unqualified-ids begin and end are looked up in the scope of class _RangeT as if by class member access lookup ([basic.lookup.classref]), and if either (or both) finds at least one declaration, begin-expr and end-expr are __range.begin() and __range.end(), respectively;
otherwise, begin-expr and end-expr are begin(__range) and end(__range), respectively, where begin and end are looked up with argument-dependent lookup ([basic.lookup.argdep]). For the purposes of this name lookup, namespace std is an associated namespace.
[ Example:
int array[5] = { 1, 2, 3, 4, 5 }; for (int& x : array) x *= 2;
In the decl-specifier-seq of a for-range-declaration, each decl-specifier shall be either a type-specifier or constexpr.
this ensures that a top-level comma operator cannot be reinterpreted as a delimiter between init-declarators in the declaration of __range.