После условных операторов для управления потоком можно разобрать циклы.
Без циклов нам бы пришлось бы дублировать код, если мы бы хотели повторять действие (либо использовать оператор goto).
Существует несколько типов циклов
for- цикл с известным количеством выполненийwhile- цикл с неизвестным количеством выполненийdo-while- цикл неизвестным количеством выполнений и пост-условиемforeach- цикл применяющийся для коллекций
Сегодня мы разберём все типы циклов за исключением foreach, потому что он имеет смысл только в контексте коллекций.
Цикл for
Этот цикл применяется в той ситуации, когда количество его выполнений известно заранее.
В большинстве IDE при написании оператора for вам предложит раскрыть такую конструкцию.
for (size_t i = 0; i < length; i++)
{
}
В некоторых случаях такой шаблон может вас подвести и заставить потратить своё время, об этом позже.
for (/* инициализация */; /* условие продолжения */; /* пост-действие */)
{
}
Таким образом можно описать части заголовка цикла - так называется всё, что идёт в скобочках после for.
Принято в этих частях записывать соответствующие части управления циклом, хотя можно обойтись вообще без них либо управлять другим образом.
Разберём самый простой пример.
for (size_t i = 0; i < 5; i++)
{
std::cout << i << std::endl;
}
0
1
2
3
4
Тут мы инициализируем переменную цикла i типа size_t значением 0. Её еще называют счётчиком цикла в таких случаях.
После инициализации у нас выполняется проверка условия i < 5. Если оно false, то цикл даже не начнёт своё выполнение.
В нашем случае на первой итерации i = 0 и поток выполнения попадёт в тело цикла.
Итерация - это одно выполнение тела цикла.
Тело цикла - это блок кода следующий за его заголовком.
Ну дак вот, при попадании на первой итерации цикла в его тела у нас выполняется вывод в консоль 0 и перенос строки.
Далее поток выполнения переходит к пост-действию - инкременту переменной цикла i.
А после этого снова переходит к шагу, который начинается с проверки условия.
Он продолжает своё выполнение до тех пор, пока условие i < 5 не станет ложным.
То есть после итерации, на которой переменная i = 4 выполняется инкремент, переменная принимает значение 5 и условие i < 5 становится ложным.
После этого происходит выход из цикла.
Типичная ошибка применения типа size_t
Один из примитивных примеров выполнения цикла - вывод значения функции на промежутке.
Давайте возьмём функцию квадрата числа и промежуток от 0 до 10.
for (size_t x = 0; x < 10; x++)
{
int y = x * x;
std::cout << std::format("x = {}, y = {}\n", x, y);
}
x = 0, y = 0
x = 1, y = 1
x = 2, y = 4
...
x = 8, y = 64
x = 9, y = 81
Как видим всё работает корректно, но если мы заходим взять промежуток от -10 до 10 то получим вот это
//C6294 Ill - defined for - loop.Loop body not executed.
for (size_t x = -10; x < 10; x++)
{
int y = x * x;
std::cout << std::format("x = {}, y = {}\n", x, y);
}
Где вывод? Его нет, он пустой.
Оформите подписку, чтобы иметь доступ ко всем публикациям без ограничений. Вы получите мгновенный доступ к полным версиям материалов, исходному коду и новым публикациям сразу после их выхода.
Я регулярно публикую материал и разборы ситуаций для различных игр, движков, а так же подходов разработки включая Internal, External и DMA.