Why can I bind rvalues to non const reference with a for loop in C++?

218 Views Asked by At

The logic of the following is confusing me. It compiles ok but the result of foo is an rvalue. It is a temporary. Why am I then allowed to get non constant references to items in the container?

https://godbolt.org/z/vEafrE

#include <array>

std::array<int,3> foo(){
    return std::array<int,3>{0,1,2};
}

int main(){
    for(int & item: foo())
        item = 0;
}

1

There are 1 best solutions below

0
On BEST ANSWER

The range based for loop has the syntax

attr(optional) for ( init-statement(optional)range_declaration : range_expression ) loop_statement

and it expands into

{
    init-statement
    auto && __range = range_expression ;
    auto __begin = begin_expr ;
    auto __end = end_expr ;
    for ( ; __begin != __end; ++__begin) {
        range_declaration = *__begin;
        loop_statement
    }
}

as you can see, the rvalue's lifetime gets extended by __range, so it's valid to have lvalue references into the collection __range binds to. Once the loop is over, __range will go out of scope destroying the rvalue object that was created.

This is why it works even though you are modifying an object that is destined to be destroyed.