C++ For Loop and Range-based For
The for loop puts the three parts of a counting loop, start, condition and step, on one line. C++ also has a range-based for that visits every element of a collection without an index.
The counting for loop
#include <iostream>
int main() {
for (int i = 1; i <= 5; i++) {
std::cout << i * i << " ";
}
std::cout << "\n";
for (int i = 10; i >= 0; i -= 5) {
std::cout << i << " ";
}
std::cout << "\n";
return 0;
}1 4 9 16 25 10 5 0
The start runs once; the condition is checked before every round; the step runs after every round. The variable i exists only inside the loop.
Nested loops
#include <iostream>
int main() {
for (int row = 1; row <= 3; row++) {
for (int col = 1; col <= 4; col++) {
std::cout << row * col << "\t";
}
std::cout << "\n";
}
return 0;
}1 2 3 4 2 4 6 8 3 6 9 12
The range-based for loop
for (element : collection) gives each element in turn. It works with strings, arrays, vectors and all standard containers, and it cannot go past the end.
#include <iostream>
#include <string>
#include <vector>
int main() {
std::vector<std::string> fruits = {"apple", "mango", "banana"};
for (const std::string& f : fruits) {
std::cout << f << " has " << f.size() << " letters\n";
}
int total = 0;
for (int n : {3, 5, 9}) {
total += n;
}
std::cout << "total " << total << "\n";
for (char c : std::string("abc")) {
std::cout << c << "-";
}
std::cout << "\n";
return 0;
}apple has 5 letters mango has 5 letters banana has 6 letters total 17 a-b-c-
const std::string& f reads each element through a reference, without copying it, and const promises not to change it. To change the elements, leave out const: for (int& n : numbers) n *= 2;.
Choosing the loop
Use the range-based for whenever you visit every element; it is shorter and cannot make index mistakes. Use the counting for when you need the index, a different step, or only part of the collection. Remember that i < size (not <=) is the right condition for indexes from 0.
Common mistakes
- Off by one:
for (int i = 0; i <= v.size(); i++)visits one element too many. Indexes go from 0 to size − 1, so the condition isi < v.size(). - Signed and unsigned:
size()returns an unsigned type; comparing it with anintindex gives a warning, and counting down with an unsigned index never goes below zero. Usestd::size_tfor indexes, or a range-basedfor. - Changing a vector while looping over it: adding or removing elements inside a range-based
forover the same vector is not allowed and can crash. Collect the changes and apply them after the loop.
Practice exercises
- Print the multiplication table of a number the user types.
- Add up the numbers from 1 to 100.
- Print a right-angled triangle of
*with nested loops. - Double every element of a vector with a range-based
forand a reference.