Урок №91. Цикл foreach

  Юрий  | 

    | 

  Обновл. 27 мая 2019  | 

 29486

 ǀ   3 

В уроке №76 мы рассматривали примеры использования цикла for для осуществления итерации по каждому элементу массива. Например:

В то время как циклы for предоставляют удобный и гибкий способ итерации по массиву, в них так же легко можно запутаться и наделать «ошибок неучтённых единиц».

Поэтому в C++11 добавили новый тип цикла — foreach (или ещё «цикл, основанный на диапазоне»), который предоставляет более простой и безопасный способ итерации по массиву (или по любой другой структуре типа списка).

Цикл foreach

Синтаксис цикла foreach следующий:

for (объявление_элемента : массив)
   стейтмент;

Выполняется итерация по каждому элементу массива, присваивая значение текущего элемента массива переменной, объявленной как элемент (объявление_элемента). В целях улучшения производительности объявляемый элемент должен быть того же типа, что и элементы массива, иначе произойдёт неявное преобразование. Рассмотрим простой пример использования цикла foreach для вывода всех элементов массива math:

Результат выполнения программы выше:

0 1 4 5 7 8 10 12 15 17 30 41

Рассмотрим детальнее, как это всё работает. При выполнении цикла foreach переменной number присваивается значение первого элемента (т.е. 0). Дальше программа выполняет стейтмент вывода значения переменной number, т.е. нуля. Затем цикл for выполняется снова и значением number-а уже является 1 (второй элемент массива). Вывод значения number выполняется снова. Цикл продолжает своё выполнение до тех пор, пока в массиве не останется непройденных элементов. В конце выполнения программа возвращает 0 обратно в операционную систему (оператор return).

Обратите внимание, переменная number не является индексом массива. Ей просто присваивается значение элемента массива в текущей итерации цикла.

Цикл foreach и ключевое слово auto


Поскольку объявляемый элемент цикла foreach должен быть того же типа, что и элементы массива, то это идеальный случай для использования ключевого слова auto, когда мы позволяем C++ вычислить тип данных элементов массива вместо нас. Например:

Цикл foreach и ссылки

В примерах выше объявляемый элемент всегда объявляется в качестве переменной (значения):

То есть каждый обработанный элемент массива копируется в переменную element. А это копирование может оказаться затратным, в большинстве случаев мы можем просто ссылаться на исходный элемент с помощью ссылки:

В примере выше в качестве объявляемого элемента цикла foreach используется ссылка на текущий элемент массива, при этом копирование этого элемента не происходит. Но, с указанием обычной ссылки, любые изменения элемента будут влиять на сам массив, что не всегда может быть желательно.

Конечно же, хорошей идеей будет сделать объявляемый элемент const, тогда вы сможете его использовать в режиме «только для чтения»:

Правило: Используйте обычные ссылки или константные ссылки в качестве объявляемого элемента в цикле foreach (в целях улучшения производительности).

Ещё один пример


Вот пример первой программы из начала этого урока, но уже с использованием цикла foreach:

Обратите внимание, здесь нам уже не нужно вручную прописывать индексацию массива. Мы можем получить доступ к каждому элементу массива непосредственно через переменную score.

Цикл foreach и не массивы

Циклы foreach работают не только с фиксированными массивами, но также и со многими другими структурами типа списка: векторы (например, std::vector), связанные списки, деревья. Не беспокойтесь, если вы не знаете, что это такое, мы ещё это всё не рассматривали. Просто помните, что циклы foreach обеспечивают гибкий и удобный способ итерации не только по массивам:

Цикл foreach не работает с указателями на массив


Для итерации по массиву, foreach должен знать длину массива. Поскольку массивы, которые распадаются в указатель, не знают своей длины, то циклы foreach с ними работать не могут!

По этой же причине циклы foreach не работают с динамическими массивами.

Могу ли я получить индекс текущего элемента?

Циклы foreach не предоставляют прямой способ получения индекса текущего элемента массива. Это связано с тем, что большинство структур, с которыми могут использоваться циклы foreach (например, связанные списки), напрямую не индексируются!

Заключение

Циклы foreach обеспечивают лучший синтаксис для итерации по массиву, когда нам нужно получить доступ ко всем элементам массива в последовательном порядке. Эти циклы предпочтительнее использовать вместо стандартных циклов for в случаях, когда они могут использоваться. Для предотвращения создания копий каждого элемента, в качестве объявляемого элемента, следует использовать ссылку.

Обратите внимание, поскольку циклы foreach были добавлены в C++11, то они не будут работать на старых компиляторах (которые не поддерживают С++11).

Тест

Это должно быть легко!

Объявите фиксированный массив со следующими именами: Sasha, Ivan, John, Orlando, Leonardo, Nina, Anton и Molly. Попросите пользователя ввести имя. Используйте цикл foreach для проверки того, не находится ли имя, введенное пользователем, уже в массиве.

Пример результата выполнения программы:

Enter a name: Sasha
Sasha was found.

Enter a name: Maruna
Maruna was not found.

Подсказка: Используйте std::string в качестве типа массива.

Ответ

Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (78 оценок, среднее: 4,97 из 5)
Загрузка...

Комментариев: 3

  1. Аватар Вячеслав:

    у меня так получилось

  2. Аватар Павел:

    У меня решение в тексте выдает сразу "Enter a name: was not found."

  3. Аватар Игорь:

Добавить комментарий

Ваш E-mail не будет опубликован. Обязательные поля помечены *