9 Statements [stmt.stmt]

9.5 Iteration statements [stmt.iter]

Операторы итерации определяют цикл.

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-statementend 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]

9.5.1 The while statement [stmt.while]

В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

9.5.2 The do statement [stmt.do]

Выражение естьcontextually converted to bool; если это преобразование сформировано неверно, значит, неверно сформирована программа.

Вdo операторе подзапрос выполняется многократно, пока значение выражения не станет равнымfalse. Проверка проводится после каждого выполнения инструкции.

9.5.3 The for statement [stmt.for]

for заявление

for ( init-statement conditionopt ; expressionopt ) statement

эквивалентно

{
	init-statement
	while ( condition ) {
		statement
		expression ;
	}
}

за исключением того, что имена, объявленные в, init-statementнаходятся в той же декларативной области, что и имена, объявленные в condition, и за исключением того, что перед повторной оценкой будет выполняться continue in statement(не заключенный в другой оператор итерации) . [ Таким образом, первый оператор определяет инициализацию цикла; условие ( ) задает тест, выполняемый по порядку перед каждой итерацией, так что цикл завершается, когда условие становится ; выражение часто определяет приращение, которое выполняется после каждой итерации. ]expressionconditionNote: [stmt.select]falseend 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]

9.5.4 The range-based for statement [stmt.ranged]

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должен определять класс или перечисление.