Loops
Loops repeat code. C++ has while and do/while for "repeat until", the classic counting for loop, and the range-based for loop — the everyday way to visit every element of a container.
while and do-while
#include <iostream> int main() { double balance = 1000.0; int years = 0; while (balance < 2000.0) { balance *= 1.05; ++years; } std::cout << "Doubled after " << years << " years\n"; int n = 10; do { std::cout << "runs at least once (n = " << n << ")\n"; } while (n < 5); }
Doubled after 15 years runs at least once (n = 10)
while checks before each pass; do/while checks after, so its body always runs at least once.
The counting for loop
#include <iostream> int main() { for (int i = 1; i <= 5; ++i) { std::cout << i << " squared is " << i * i << '\n'; } for (int i = 10; i > 0; i -= 3) std::cout << i << ' '; std::cout << '\n'; }
1 squared is 1 2 squared is 4 3 squared is 9 4 squared is 16 5 squared is 25 10 7 4 1
The three parts are the start, the condition checked before each pass, and the step after each pass.
Range-based for
To visit every element of a container, the range-based for loop is clearer and can't go out of bounds:
#include <iostream> #include <string> #include <vector> int main() { std::vector<double> prices{3.50, 12.00, 7.25}; double total = 0; for (double p : prices) total += p; std::cout << "total " << total << '\n'; for (char c : std::string{"abc"}) std::cout << c << '-'; std::cout << '\n'; for (int n : {2, 3, 5, 7}) std::cout << n << ' '; std::cout << '\n'; }
total 22.75 a-b-c- 2 3 5 7
Copies, references and const references
The loop variable is a copy of each element by default, so changing it changes nothing in the container. The compiler even notices:
#include <vector> int main() { std::vector<int> scores{70, 85, 90}; for (int s : scores) s += 5; // changes copies: no effect return scores[0]; }
main.cpp:5:14: warning: variable 's' set but not used [-Wunused-but-set-variable]
Use a reference (&) to change elements in place, and a const reference to avoid copying large elements you only read:
#include <iostream> #include <string> #include <vector> int main() { std::vector<int> scores{70, 85, 90}; for (int& s : scores) s += 5; // changes the elements for (int s : scores) std::cout << s << ' '; std::cout << '\n'; std::vector<std::string> names{"Ada", "Grace", "Linus"}; for (const auto& name : names) { // no copies, read-only std::cout << name << " (" << name.size() << ")\n"; } }
75 90 95 Ada (3) Grace (5) Linus (5)
const auto& is the right default for reading containers of anything bigger than a number.
break and continue
#include <iostream> #include <vector> int main() { std::vector<int> readings{21, -999, 23, 22, -999, 25, 99, 24}; int sum = 0, used = 0; for (int r : readings) { if (r == -999) continue; // skip sensor errors if (r > 50) break; // stop at the first impossible value sum += r; ++used; } std::cout << used << " readings, sum " << sum << '\n'; }
4 readings, sum 91
Nested loops
#include <iomanip> #include <iostream> int main() { for (int row = 1; row <= 4; ++row) { for (int col = 1; col <= 4; ++col) { std::cout << std::setw(4) << row * col; } std::cout << '\n'; } }
1 2 3 4 2 4 6 8 3 6 9 12 4 8 12 16
To leave several nested loops at once, put them in a function and return.
Looping with an index
When you need the position as well as the element, a counting loop over size() works. Use std::size_t (unsigned) to match the container's size type, which avoids sign-comparison warnings:
#include <iostream> #include <string> #include <vector> int main() { std::vector<std::string> podium{"Ana", "Ben", "Chloe"}; for (std::size_t i = 0; i < podium.size(); ++i) { std::cout << i + 1 << ". " << podium[i] << '\n'; } }
1. Ana 2. Ben 3. Chloe
Try it yourself
Print the prime numbers below 50.
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47