A range-based for loop iterates over every element of a sequence without an explicit index and no explicit step of iteration. The loop variable is automatically assigned one value at a time, and the loop body may operate on that value with no reference to the underlying array.
int numbers[5]{10, 20, 30, 40, 50};
// Visit each element in the range directly
for (int value : numbers)
{
std::cout << value << '\n';
}
The header takes a variable and a sequence to iterate over. The next element in the array is copied into the loop variable on each iteration, the loop body is executed with that loop variable, and the process is repeated until every element of the array has been read.
The programmer does not have to keep track of whether the loop index has gone out of bounds.
The start, end, and progression steps are implicit to the compiler. The only task the programmer has is to perform operations within the range. This has the added advantage of eliminating the one-off error issues of writing the index manually.
A new variable is created each time. Any value is overwritten in each iteration, and an assignment to the loop variable is an assignment to the next value in the array only if, when declared, the loop variable is made a reference to the element in the array.
If the values themselves need to be modified using a reference, this must be indicated at declaration by using an ampersand as shown here:
int scores[4]{5, 8, 3, 9};
// Pass this argument by reference instead of copying it
for (int& score : scores)
{
score = score * 2;
}
The ampersand makes the loop variable an alias or reference for the given array element. Now, each assignment to the element in the array can be performed simply with the loop variable.
If the elements in the sequence do not need to be modified, the value simply becomes a const reference:
// Bind by reference without allowing modification through it
for (const int& score : scores)
{
std::cout << score << '\n';
}
A const reference also avoids copying, yet it prohibits modification of any elements through the loop variable.
Nested range-based for loops are also possible, to iterate over sequences within sequences. While more common in containers than in multidimensional arrays, the principles remain the same as those of classic loops; the inner loop runs to completion before the outer loop progresses to the next element.
int table[3][2]{
{1, 2},
{3, 4},
{5, 6}
};
// Visit the values selected by this loop
for (int (&row)[2] : table)
{
for (int cell : row)
{
std::cout << cell << ' ';
}
std::cout << '\n';
}
The range-based for loop requires a sequence where its boundaries are known, hence cannot be performed on an unpointed element, only fixed-size arrays work, where array dimensions are known at compile time:
int values[4]{2, 4, 6, 8};
int* pointer{values};
// This works because the array size is known.
for (int value : values)
{
std::cout << value << '\n';
}
// A range-based for loop cannot use pointer alone.
// for (int value : pointer)
// {
// }
In cases of index manipulation being needed, iteration from behind the array or steps differing from 1, the standard three-part for loop is still a preferable option.
The first loop below iterates through and prints the unmodified array elements.
The second loop iterates through and modifies array elements by assigning new values using a reference.
The third loop iterates and prints the modified elements.
The last pair of nested loops iterates through a small, two-dimensional array using a nested range-based for loop.
In all cases, the iteration details are handled by the loop itself, allowing simple operations to be performed.
#include <iostream>
int main()
{
int data[6]{2, 4, 6, 8, 10, 12};
for (int number : data)
{
std::cout << number << ' ';
}
std::cout << '\n';
for (int& number : data)
{
number = number + 1;
}
for (int number : data)
{
std::cout << number << ' ';
}
std::cout << '\n';
int table[3][2]{
{1, 2},
{3, 4},
{5, 6}
};
// Pass the object's address to the function
for (int (&row)[2] : table)
{
for (int cell : row)
{
std::cout << cell << ' ';
}
std::cout << '\n';
}
}
If the task requires iteration over an array without access to index values and it doesn't take long to finish, this is the shortest and simplest iteration structure available.
Exercise: Range-Based for LoopsStarter code, hints and solutionOpenClose
Practice: Range-Based for Loops
Work through the mission, reveal hints only when needed, and compare your result with the model solution.
Your challenge
Extend data to seven elements by adding 14. Predict both traversals and explain why the reference loop changes the array while the value loop does not.
Mission checklist
- Run the starter as a baseline, then predict the change requested in Your challenge.
- Make that change in your editor; use the lesson-specific hints if you need help.
- Compile and run your answer, then compare with the worked solution and explain the result.
Starter program
This is the working baseline, not the completed answer. Compile as C++20, then make the change described above.
#include <iostream>
int main()
{
int data[6]{2, 4, 6, 8, 10, 12};
for (int number : data)
{
std::cout << number << ' ';
}
std::cout << '\n';
for (int& number : data)
{
number = number + 1;
}
for (int number : data)
{
std::cout << number << ' ';
}
std::cout << '\n';
int table[3][2]{
{1, 2},
{3, 4},
{5, 6}
};
// Pass the object's address to the function
for (int (&row)[2] : table)
{
for (int cell : row)
{
std::cout << cell << ' ';
}
std::cout << '\n';
}
}Hints
for (int number : data) copies each element; for (int& number : data) refers to the element itself. Only the reference loop writes the incremented values back into data.
A range-based loop has no numeric stopping condition to extend. To visit one more element, enlarge data to seven elements and add an initializer; preserve the & in the modifying loop.
Worked solution
A range-based loop has no explicit numeric condition. I enlarged data from six elements to seven and added 14, so each loop over data visits one extra element. The int& loop updates the actual elements, making the final new value 15.
#include <iostream>
int main()
{
int data[7]{2, 4, 6, 8, 10, 12, 14};
for (int number : data)
{
std::cout << number << ' ';
}
std::cout << '\n';
for (int& number : data)
{
number = number + 1;
}
for (int number : data)
{
std::cout << number << ' ';
}
std::cout << '\n';
int table[3][2]{
{1, 2},
{3, 4},
{5, 6}
};
// Pass the object's address to the function
for (int (&row)[2] : table)
{
for (int cell : row)
{
std::cout << cell << ' ';
}
std::cout << '\n';
}
}
Example output
2 4 6 8 10 12 14
3 5 7 9 11 13 15
1 2
3 4
5 6
0 comments
No comments yet. Be the first.