Spec-Zone.ru › C++

for цикл

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

Синтаксис

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

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

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

Условие

condition может быть как выражением, так и простым объявлением.

  • Если синтаксически его можно интерпретировать как объявление структурированной привязки, оно интерпретируется как объявление структурированной привязки.
(начиная с 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)
  • Декларатор не может задавать функцию или массив.
  • последовательность спецификаторов типа(до C++11)последовательность спецификаторов объявления может содержать только спецификаторы типа и constexpr, а также(начиная с C++11) не может определять класс или перечисление.

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

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

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

  • expression в его инициализаторе не может иметь тип массива.
  • Последовательность спецификаторов объявления может содержать только спецификаторы типа и constexpr.

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

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

Пояснение

Оператор for эквивалентен следующему:

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

}

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

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

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

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

Примечания

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

for (;;)
    int n;
// n goes out of scope

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

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

for (int i = 0;;)
{
    long i = 1;   // valid C, invalid C++
    // ...
}

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

for

Пример

#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';
}

Вывод:

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

См. также

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

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/language/for

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API