I have a class
class Person {
// some other fields for this object
std::vector<string> relatives;
}
then a util function which returns a list of Person
std::vector<Person> getSomePerson() {
// implementation details...
}
Now I want to loop through:
for (auto&& p: getSomePerson()) { <---- do I need the rvalue reference???
// use p
some_other_vector.insert(
std::make_move_iterator(p.relatives.begin()),
std::make_move_iterator(p.relatives.end())
)
}
Question: do I need the rvalue reference? Does it make any difference than using simple reference here?
In your case:
for (auto&& p: getSomePerson()) {
for (auto& p: getSomePerson()) {
those two lines are completely identical.
auto&&
here is a forwarding reference. It will deduce to be an rvalue or lvalue reference depending on what it is initialized with.
The range being iterated over is an rvalue of type vector. Its iterator's operator*
returns an lvalue reference.
So p
will be an lvalue reference to a Person
.
auto&&
can be interpreted here (and many other spots) as "I do not care what I am binding to, but don't make any extra copies". It is a reasonable default for a for(:)
loop.
If your range returned values, auto&&
would become an rvalue reference, and reference lifetime extension would occur. auto&
would fail to compile.
auto const&
is another reasonable option here; it is much like auto&&
, but you also promise not to modify the thing you are referring to.