5.4.3. Серийный оператор for
Новый стандарт ввел упрощенный оператор for, который перебирает элементы контейнера или другой последовательности. Синтаксис серийного оператора for (range for) таков:
for (объявление : выражение)
оператор
выражение должно представить некую последовательность, такую, как список инициализации (см. раздел 3.3.1), массив (см. раздел 3.5), или объект такого типа, как vector или string, у которого есть функции-члены begin() и end(), возвращающие итераторы (см. раздел 3.4).
объявление определяет переменную. Каждый элемент последовательности должен допускать преобразование в тип переменной (см. раздел 4.11). Проще всего гарантировать соответствие типов за счет использования спецификатора типа auto (см. раздел 2.5.2). Так компилятор выведет тип сам. Если необходима запись в элементы последовательности, то переменная цикла должна иметь ссылочный тип.
На каждой итерации управляющая переменная определяется и инициализируется следующим значением последовательности, а затем выполняется оператор. Как обычно, оператор может быть одиночным оператором или блоком. Выполнение завершается, когда все элементы обработаны.
Несколько таких циклов уже было представлено, но для завершенности рассмотрим цикл, удваивающий значение каждого элемента в векторе:
vector<int> v = {0,1,2,3,4,5,6,7,8,9};
// для записи в элементы переменная диапазона должна быть ссылкой
for (auto &r : v) // для каждого элемента вектора v
r *= 2; // удвоить значение каждого элемента вектора v
Заголовок for объявляет, что управляющая переменная цикла r связана с вектором v. Чтобы позволить компилятору самостоятельно вывести тип переменной r, используем спецификатор auto. Поскольку предполагается изменение значений элементов вектора v, объявим переменную r как ссылку. При присвоении ей значений в цикле фактически присваивается значение элементу, с которым связана переменная r в данный момент.
Вот эквивалентное определение серийного оператора for в терминах традиционного цикла for:
for (auto beg = v.begin(), end = v.end(); beg != end; ++beg) {
auto &r = *beg; // для изменения элементов r должна быть ссылкой
r *= 2; // удвоить значение каждого элемента вектора v
}
Теперь, когда известно, как работает серийный оператор for, можно понять, почему в разделе 3.3.2 упоминалось о невозможности его использования для добавления элементов к вектору или другому контейнеру. В серийном операторе for кешируется значение end(). Если добавить или удалить элементы из последовательности, сохраненное значение end() станет неверным (см. раздел 3.4.1). Более подробная информация по этой теме приведена в разделе 9.3.6.
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОК