Операторы итерации определяют цикл.
iteration-statement: while ( condition ) statement do statement while ( expression ) ; for ( init-statement conditionopt ; expressionopt ) statement for ( for-range-declaration : for-range-initializer ) statement
for-range-declaration: attribute-specifier-seqopt decl-specifier-seq declarator attribute-specifier-seqopt decl-specifier-seq ref-qualifieropt [ identifier-list ]
for-range-initializer: expr-or-braced-init-list
См[dcl.meaning] для дополнительного attribute-specifier-seqв for-range-declaration. [ Заканчивается точкой с запятой. ] Note: init-statement — end note
Подстрока в iteration-statementнеявно определяет блок,scope который вводится и выходит каждый раз в цикле.
Если подзапрос в операторе итерации является единственным оператором, а не a compound-statement, это как если бы оно было переписано как составное выражение, содержащее исходное выражение. [ Example:
while (--x >= 0) int i;
можно эквивалентно переписать как
while (--x >= 0) { int i; }
Таким образом, послеwhile заявления,i больше не входит в сферу действия. ] — end example
Если имя, введенное в init-statementили for-range-declaration повторно объявлено во внешнем блоке подзапуска, программа имеет неправильный формат . [ Example:
void f() { for (int i = 0; i < 10; ++i) int i = 0; // error: redeclaration for (int i : { 1, 2, 3 }) int i = 1; // error: redeclaration }
— end example ]
Вwhile операторе подзапрос выполняется многократно, пока значение условия ([stmt.select]) не станет равнымfalse. Проверка проводится перед каждым выполнением подзапуска.
Когда условиемwhile оператора является объявление, область объявляемой переменной простирается от нее point of declaration до конца . Утверждение видаwhile statementwhile
while (T t = x) statement
эквивалентно
label: { // start of condition scope T t = x; if (t) { statement goto label; } } // end of condition scope
Переменная, созданная в условии, уничтожается и создается при каждой итерации цикла. [ 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;
}
В цикле while конструктор и деструктор вызываются дважды: один раз для успешного условия и один раз для невыполненного условия. ] — end example
Выражение естьcontextually converted to bool; если это преобразование сформировано неверно, значит, неверно сформирована программа.
for заявление
for ( init-statement conditionopt ; expressionopt ) statement
эквивалентно
{ init-statement while ( condition ) { statement expression ; } }
за исключением того, что имена, объявленные в, init-statementнаходятся в той же декларативной области, что и имена, объявленные в condition, и за исключением того, что перед повторной оценкой будет выполняться continue in statement(не заключенный в другой оператор итерации) . [ Таким образом, первый оператор определяет инициализацию цикла; условие ( ) задает тест, выполняемый по порядку перед каждой итерацией, так что цикл завершается, когда условие становится ; выражение часто определяет приращение, которое выполняется после каждой итерации. ]expressioncondition Note: [stmt.select]false — end note
Один или оба из condition и expressionможно опустить. Отсутствие condition делает подразумеваемоеwhile предложение эквивалентнымwhile(true).
Если init-statementэто объявление, объем объявленного имени (имен) расширяется до концаfor оператора. [ 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 Заявление на основе диапазона
for ( for-range-declaration : for-range-initializer ) statement
эквивалентно
{ auto &&__range = for-range-initializer ; auto __begin = begin-expr ; auto __end = end-expr ; for ( ; __begin != __end; ++__begin ) { for-range-declaration = *__begin; statement } }
куда
если for-range-initializerесть expression, он рассматривается, как если бы он был заключен в круглые скобки (так что оператор запятой не может быть интерпретирован как разделяющий два init-declarators);
__range,__beginи__end - переменные, определенные только для демонстрации; а также
begin-expr иend-expr определяются следующим образом:
если for-range-initializer- выражение типа массиваR,begin-expr иend-expr - __range и__range + __bound, соответственно, где__bound - граница массива. ЕслиR это массив с неизвестной границей или массив неполного типа, программа имеет неправильный формат;
если for-range-initializerявляется выражением типа классаC, unqualified-ids begin иend ищутся в области видимости,C как если бы byclass member access lookup, и если один из них (или оба) находит по крайней мере одно объявление,begin-expr и end-expr являются__range.begin() и__range.end(), соответственно;
в противном случаеbegin-expr иend-expr являютсяbegin(__range) иend(__range), соответственно, гдеbegin иend ищутся вassociated namespaces. [ Note: Обычныйunqualified lookup не выполняется. ] — end note
[ Example:
int array[5] = { 1, 2, 3, 4, 5 }; for (int& x : array) x *= 2;
— end example ]
В decl-specifier-seqa for-range-declarationкаждый decl-specifierдолжен быть либо a, type-specifier либоconstexpr. Не decl-specifier-seqдолжен определять класс или перечисление.