Range-based
for
loop
(since C++11)
Выполняет цикл for по диапазону.
Используется как более читаемая альтернатива традиционному for циклу для работы с диапазоном значений, например, со всеми элементами контейнера.
Содержание
Синтаксис
ОбъяснениеПриведённый выше синтаксис генерирует код, эквивалентный следующему за исключением расширения времени жизни временных объектов range-initializer (см. ниже ) (начиная с C++23) (переменные и выражения, заключённые в /* */ , приведены только для демонстрации):
range-initializer вычисляется для инициализации последовательности или диапазона для итерации. Каждый элемент последовательности, в свою очередь, разыменовывается и используется для инициализации переменной с типом и именем, указанными в item-declaration . item-declaration может быть одним из следующих:
Экспозиционные выражения /* begin-expr */ и /* end-expr */ определяются следующим образом:
Если цикл необходимо прервать внутри statement , в качестве завершающей инструкции можно использовать break statement . Если текущую итерацию необходимо прервать внутри statement , можно использовать continue statement в качестве сокращения. Если имя, введённое в init-statement , переобъявляется в самом внешнем блоке statement , программа является некорректной: for (int i : {1, 2, 3}) int i = 1; // ошибка: повторное объявление Инициализатор временного диапазонаЕсли range-initializer возвращает временный объект, время его жизни продлевается до конца цикла, как указано при связывании с пересылаемой ссылкой /* range */ . Время жизни всех временных объектов в range-initializer не продлевается за исключением случаев, когда они должны быть уничтожены в конце range-initializer (начиная с C++23) . // если foo() возвращает по значению for (auto& x : foo().items()) { /* ... */ } // до C++23 неопределённое поведение
ПримечанияЕсли range-initializer является braced-enclosed initializer list , /* range */ выводится как ссылка на std::initializer_list . Безопасно и, фактически, предпочтительно в обобщённом коде использовать выведение для пересылающей ссылки, for ( auto && var : sequence ) .
Интерпретация через члены используется, если тип диапазона имеет член с именем "
Хотя переменная, объявленная в item-declaration , обычно используется в statement , это не является обязательным требованием.
При использовании с (неконстантным) объектом, имеющим семантику копирования при записи, цикл
for
по диапазону может вызвать глубокое копирование путем (неявного) вызова неконстантной функции-члена
Ключевые словаПример
Запустить этот код
#include <iostream> #include <vector> int main() { std::vector<int> v = {0, 1, 2, 3, 4, 5}; for (const int& i : v) // доступ по константной ссылке std::cout << i << ' '; std::cout << '\n'; for (auto i : v) // доступ по значению, тип i - int std::cout << i << ' '; std::cout << '\n'; for (auto&& i : v) // доступ по forwarding reference, тип i - int& std::cout << i << ' '; std::cout << '\n'; const auto& cv = v; for (auto&& i : cv) // доступ по f-d reference, тип i - const int& std::cout << i << ' '; std::cout << '\n'; for (int n : {0, 1, 2, 3, 4, 5}) // инициализатором может быть // список инициализации в фигурных скобках std::cout << n << ' '; std::cout << '\n'; int a[] = {0, 1, 2, 3, 4, 5}; for (int n : a) // инициализатором может быть массив std::cout << n << ' '; std::cout << '\n'; for ([[maybe_unused]] int n : a) std::cout << 1 << ' '; // переменная цикла не обязана использоваться std::cout << '\n'; for (auto n = v.size(); auto i : v) // init-statement (C++20) std::cout << --n + i << ' '; std::cout << '\n'; for (typedef decltype(v)::value_type elem_t; elem_t i : v) // объявление typedef как init-statement (C++20) std::cout << i << ' '; std::cout << '\n'; for (using elem_t = decltype(v)::value_type; elem_t i : v) // объявление псевдонима как init-statement (C++23) std::cout << i << ' '; std::cout << '\n'; } Вывод: 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 1 1 1 1 1 1 5 5 5 5 5 5 0 1 2 3 4 5 0 1 2 3 4 5 Отчеты о дефектахСледующие отчеты об изменениях поведения, влияющие на дефекты, были применены задним числом к ранее опубликованным стандартам C++.
См. также
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||