Demystifying C++ - Range-Based for Loops
Jump to navigation
Jump to search
Range-based for loops in modern C++ offer a neat and intuitive way to iterate over the elements of a container or array. Compared to traditional loops where indices or iterators need to be explicitly managed, range-based for-loops offer a more concise and less error-prone syntax.
Here's the substitute code for the loop that is written in the C++17 standard:
| Substitute Code | for (range-declaration : range-expression) {
...
}
|
auto && __range = range-expression;
auto __begin = begin-expr;
auto __end = end-expr;
for ( ; __begin != __end; ++__begin) {
range-declaration = *__begin;
...
}
|
|---|
The following example showcases the C-code for a simple instance with `std::initializer_list`. The code follows the principle of the substitute code:
| Range-based for loop
with std::initializer_list |
#include <initializer_list>
void work(int);
void func() {
for (int i : {1, 2, 3}) {
work(i);
}
}
|
struct std::initializer_list<int> {
const int *__begin_;
size_t __size_;
};
inline const int *std::initializer_list<int>::begin(const struct std::initializer_list<int> *this) {
return this->__begin_;
}
inline const int *std::initializer_list<int>::end(const struct std::initializer_list<int> *this) {
return this->__begin_ + this->__size_;
}
void work(int);
void func(void) {
{
const int init[3] = {1, 2, 3};
struct std::initializer_list<int> tmpExpr1 = {init, 3};
struct std::initializer_list<int> *__range1 = &tmpExpr1;
const int *__begin1 = std::initializer_list<int>::begin(__range1);
const int *__end1 = std::initializer_list<int>::end(__range1);
for (; __begin1 != __end1; ++__begin1) {
int i = *__begin1;
work(i);
}
}
}
|
|---|
This mechanism ensures that the correct lifespan of temporary variables is maintained, preserving the intended behavior of the original C++ code when translating to C.