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:



Table Of Contents