Range-Based For

suggest change

for loops can be used to iterate over the elements of a iterator-based range, without using a numeric index or directly accessing the iterators:

vector<float> v = {0.4f, 12.5f, 16.234f};

for (auto val: v)
{
    std::cout << val << " ";
}

std::cout << std::endl;

This will iterate over every element in v, with val getting the value of the current element. The following statement:

for (for-range-declaration : for-range-initializer ) statement

is equivalent to:

{
    auto&& __range = for-range-initializer;
    auto __begin = begin-expr, __end = end-expr;
    for (; __begin != __end; ++__begin) {
        for-range-declaration = *__begin;
        statement
    }
}

In C++ 17:

{
    auto&& __range = for-range-initializer;
    auto __begin = begin-expr;
    auto __end = end-expr; // end is allowed to be a different type than begin in C++17
    for (; __begin != __end; ++__begin) {
        for-range-declaration = *__begin;
        statement
    }
}

This change was introduced for the planned support of Ranges TS in C++20.

In this case, our loop is equivalent to:

{
    auto&& __range = v;
    auto __begin = v.begin(), __end = v.end();
    for (; __begin != __end; ++__begin) {
        auto val = *__begin;
        std::cout << val << " ";
    }
}

Note that auto val declares a value type, which will be a copy of a value stored in the range (we are copy-initializing it from the iterator as we go). If the values stored in the range are expensive to copy, you may want to use const auto &val. You are also not required to use auto; you can use an appropriate typename, so long as it is implicitly convertible from the range’s value type.

If you need access to the iterator, range-based for cannot help you (not without some effort, at least).

If you wish to reference it, you may do so:

vector<float> v = {0.4f, 12.5f, 16.234f};

for(float &val: v)
{
    std::cout << val << " ";
}

You could iterate on const reference if you have const container:

const vector<float> v = {0.4f, 12.5f, 16.234f};

for(const float &val: v)
{
    std::cout << val << " ";
}

One would use forwarding references when the sequence iterator returns a proxy object and you need to operate on that object in a non-const way. Note: it will most likely confuse readers of your code.

vector<bool> v(10);

for(auto&& val: v)
{
    val = true;
}

The “range” type provided to range-based for can be one of the following:

Feedback about page:

Feedback:
Optional: your email if you want me to get back to you:


Loops:
* Range-Based For

Table Of Contents
8 Arrays
11 Loops
39 Streams
51 Unions
56 Lambdas
60 SFINAE
62 RAII
67 Sorting
84 RTTI
87 Scopes
104 Profiling
107 Recursion
117 Iteration
125 Alignment
134 Semaphore
136 Debugging
139 Mutexes
142 decltype