C++ Notes to Self: Ranged Based for Loop
C/C++
‘The range based for loop is added in C++ 11 standard and is a more compact form of its traditional equivalent.’ [tutorialspoint.com]
Range based for loop allows for the iteration over arrays and containers without the need for an index variable. It can be used on any object that behaves like a range type such as C++ containers or initializer list.
A few subtleties about the range-based for loop:
- Instead of declaring the type of the indexer, we can declare it as
auto
. - On each iteration, a copy is created and given to the indexer. To avoid this overhead, we declare the indexer variable as a reference.
- To enforce read-only semantics within the loop, declare the indexer as a
const
.
What are the differences between C-style and range-based for loops?
- The for-loop uses index-based iteration. The range-based loop does not.
- The for-loop requires a condition that will terminate the loop. The range-based loop supplies its own end condition.
- We need to manually increment or decrement the index variable in the for-loop. We don’t need to do this in the range-based loop, thereby avoiding any mistakes.
- Because we manually adjust the index variable, the for-loop gives finer control over the iteration. With range-based loop, the iteration doesn’t deviate at all.
Underneath the hood, the range-based loop relies on std::begin()
and std::end()
that are defined for all C++ containers, arrays and initializer lists. (See code below.) A user-defined class that behaves as a range type and works with iterators needs to implement the features these C++ containers have.
#include <iostream>
using namespace std;
int main(int argc, char **argv) {
int arr[]{1,2,3,4};
for(int x: arr) {
cout << x << " ";
}
cout << endl;
for(const int &y: arr) { // To avoid copy semantics use reference variable
cout << y << " ";
}
cout << endl;
for(const auto &z: { 111, 222, 333, 444}) {
cout << z << " ";
}
cout << endl;
int mlist[] {10, 20, 30, 40};
const int *mstart = std::begin(mlist);
const int *mend = std::end(mlist);
while(mstart != mend) {
cout << *mstart++ << " ";
}
cout << endl;
return 0;
}