Hi I have a quick question - over here it says ranged-based for loops of the form
for ( init-statement (optional) range-declaration : range-expression )
are equivalent to the code:
{
auto && __range = range-expression ;
for (auto __begin = begin-expr, __end = end-expr; __begin != __end; ++__begin)
{
range-declaration = *__begin;
loop-statement
}
}
So if you do
std::vector<datatype> vector1;
for (auto& datatype : vector1)
it's perfectly acceptable. However if you do
std::vector<datatype>&& vector2 = vector1;
or
std::vector<datatype>&& vector2(vector1);
it doesn't compile. As far as I know you cannot initialize an rvalue reference with an lvalue like vector1. What exactly is going on here and what is the difference between the ranged-based for loop's underlying code and the assignment/construct statements? Thanks!
As you observed, std::vector<datatype>&&
is indeed an rvalue reference,
and it cannot be bind to an lvalue like vector1
.
However, in this statement:
auto && __range = range-expression;
__range
is not an rvalue reference.
It is in fact a Forwarding reference and can therefore bind to either rvalue or lvalue.
The key difference is the usage of auto
in the latter case. It makes it equivalent to T && x
where T is a template parameter, as in the following example from the documentation above:
template<class T>
int f(T&& x) // x is a forwarding reference
{
return g(std::forward<T>(x)); // and so can be forwarded
}
A side note:
Forwarding reference are related to the issue of perfect forwarding. See more about it here.