2

In these questions (also here) there is recommendation to write code like:

for( auto&& v : arr )

But doesn't moving the data from arr into v clobber the array arr? How can this style of loop be safe at all?

bobobobo
  • 64,917
  • 62
  • 258
  • 363
  • 2
    `v` is a reference type, not an object type. The values in `arr` are not sequentially moved into `v`. `v` is just a different reference to a different element of `arr` each iteration. There is no change to `arr` unless you manipulate `v` yourself in the loop body. – François Andrieux May 11 '21 at 17:57
  • 1
    This is the recommended form to use *if you want to modify the object you are iterating over*. Use `const auto &` if you do not want to modify it. – Chris Dodd May 11 '21 at 18:05
  • @ChrisDodd Why is `&&` recommended over `&`? Why not write `for( auto& v : arr )` instead? – bobobobo Jul 05 '21 at 15:06
  • @bobobobo: See the links in the question -- `auto &&` also allows you to bind to unnamed temp rvalues (such as `vector` proxies), while `auto &` does not. – Chris Dodd Jul 06 '21 at 00:20

1 Answers1

4

First, auto&& is not an rvalue reference. It is called a forwarding reference and it can either be an lvalue reference, or rvalue reference, depending on if the initializer is an lvalue or rvalue.

In this case arr is a named object, so auto&& is actually the same as auto& in this case.

Lets pretend then arr is an rvalue and auto&& is actually an rvalue reference, you still don't have to worry. A reference is just an alias to the source object, it doesn't actually do anything to the source object. No move will happen as no move operation is taking place. All you are doing is referring to the element. You'd need code in the loop like

something = std::move(v); // move is required here, even though v is an rvalue reference
                          // because since it has a name, it is an lvalue

in order to move what v is referring to.


With the loop as is, the biggest concern is that you can change the values stored in arr since v has non-const access to arr. Using

for (const auto& v : arr)

lets you still accept lvalues and rvalues, but also does not allow you to modify the elements.

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • I guess the point of my question is why have the second `&`? Why not write `for (auto& v : arr)` instead? – bobobobo Jul 05 '21 at 15:05