Namespaces
Variants

for loop

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
for
range- for (C++11)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

Условно выполняет оператор повторно, при этом оператору не требуется управлять условием цикла.

Содержание

Синтаксис

attr  (необязательно) for ( init-statement condition  (необязательно) ; expression  (необязательно) ) statement
attr - (since C++11) любое количество attributes
init-statement - один из
  • expression statement (который может быть пустым оператором ; )
  • simple declaration (обычно объявление переменной-счётчика цикла с инициализатором), может объявлять произвольное количество переменных или structured bindings (since C++17)
(since C++23)

Обратите внимание, что любой init-statement должен заканчиваться точкой с запятой. Поэтому его часто неформально описывают как выражение или объявление, за которым следует точка с запятой.

condition - condition
expression - expression (обычно выражение, увеличивающее счётчик цикла)
statement - statement (обычно составной оператор)

Условие

Условием может быть либо condition , либо expression , либо simple declaration .

  • Если синтаксически возможно разрешить как structured binding объявление, оно интерпретируется как объявление structured binding.
(since C++26)
  • Если это может быть синтаксически разрешено как выражение, оно трактуется как выражение. В противном случае оно трактуется как объявление которое не является объявлением структурированной привязки (начиная с C++26) .

Когда управление достигает условия, условие даёт значение, которое используется для определения, будет ли statement выполнена.

Выражение

Если condition является выражением, возвращаемое им значение — это значение выражения, контекстно преобразованное в bool . Если это преобразование некорректно, программа является некорректной.

Объявление

Если condition является простым объявлением, возвращаемое значение - это значение переменной решения (см. ниже), контекстно преобразованное в bool . Если это преобразование некорректно, программа является некорректной.

Объявление без структурированной привязки

Объявление имеет следующие ограничения:

  • Синтаксически соответствует следующей форме:
  • type-specifier-seq declarator = assignment-expression
(до C++11)
  • attribute-specifier-seq (опционально) decl-specifier-seq declarator brace-or-equal-initializer
(начиная с C++11)

Переменная решения объявления - это объявленная переменная.

Объявление структурированной привязки

Объявление имеет следующие ограничения:

Переменной решения объявления является введённая переменная e введённая объявлением .

(начиная с C++26)

Объяснение

Оператор for эквивалентный:

{
инициализирующее-выражение
while ( условие )
{
оператор
выражение ;
}

}

За исключением того, что

  • Область видимости init-statement и область видимости condition совпадают.
  • Область видимости statement и область видимости expression не пересекаются и вложены в область видимости init-statement и condition .
  • Выполнение continue statement в statement приведет к вычислению expression .
  • Пустой condition эквивалентен true .

Если цикл необходимо прервать внутри statement , в качестве завершающей инструкции можно использовать break statement .

Если текущую итерацию необходимо прервать внутри statement , в качестве сокращения можно использовать continue statement .

Примечания

Как и в случае с while циклом, если statement не является составным оператором, область видимости переменных, объявленных в нём, ограничивается телом цикла, как если бы это был составной оператор.

for (;;)
    int n;
// n выходит из области видимости

В рамках гарантии прогресса C++ поведение является неопределённым , если цикл не являющийся тривиальным бесконечным циклом (начиная с C++26) без наблюдаемого поведения не завершается. Компиляторам разрешено удалять такие циклы.

В то время как в C имена, объявленные в области видимости init-statement и condition , могут быть переопределены в области видимости statement , в C++ это запрещено:

for (int i = 0;;)
{
    long i = 1;   // корректно в C, некорректно в C++
    // ...
}

Ключевые слова

for

Пример

#include <iostream>
#include <vector>
int main()
{
    std::cout << "1) типичный цикл с одним оператором в теле:\n";
    for (int i = 0; i < 10; ++i)
        std::cout << i << ' ';
    std::cout << "\n\n" "2) init-statement может объявлять несколько имён,\n"
                 "если они используют одинаковый decl-specifier-seq:\n";
    for (int i = 0, *p = &i; i < 9; i += 2)
        std::cout << i << ':' << *p << ' ';
    std::cout << "\n\n" "3) условие может быть объявлением:\n";
    char cstr[] = "Hello";
    for (int n = 0; char c = cstr[n]; ++n)
        std::cout << c;
    std::cout << "\n\n" "4) init-statement может использовать спецификатор типа auto:\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 может быть выражением:\n";
    int n = 0;
    for (std::cout << "Начало цикла\n";
         std::cout << "Проверка цикла\n";
         std::cout << "Итерация " << ++n << '\n')
    {
        if (n > 1)
            break;
    }
    std::cout << "\n" "6) конструкторы и деструкторы объектов, созданных\n"
                 "в теле цикла, вызываются на каждой итерации:\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 может использовать 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';
}

Вывод:

1) типичный цикл с одним оператором в теле:
0 1 2 3 4 5 6 7 8 9
2) init-statement может объявлять несколько имён,
если они используют одинаковый decl-specifier-seq:
0:0 2:2 4:4 6:6 8:8
3) условие может быть объявлением:
Hello
4) init-statement может использовать спецификатор типа auto:
3 1 4 1 5 9
5) init-statement может быть выражением:
Начало цикла
Проверка цикла
Итерация 1
Проверка цикла
Итерация 2
Проверка цикла
6) конструкторы и деструкторы объектов, созданных
в теле цикла, вызываются на каждой итерации:
S::S(0, 5); S::~S()
S::S(1, 4); S::~S()
S::S(2, 3); S::~S()
7) init-statement может использовать structured bindings:
4 5 6

Смотрите также

цикл for по диапазону (C++11) выполняет цикл по диапазону