0

Since RVO was standard guaranteed it's common to have container returning functions e.g.:

std::vector<MyClass> get_elements() { 
  ...
}

in such cases I've seen two styles of range-for iterating over the return value (x-value):

for (auto const &e : get_elements()) // 1. Binding each element to a const reference
for (auto &&e      : get_elements()) // 2. Binding each element to an r-value reference

Is one of the two preferred/encouraged or are they any different?

Lorah Attkins
  • 5,331
  • 3
  • 29
  • 63
  • 3
    `std::function` isn't a container. – HolyBlackCat Apr 27 '23 at 09:00
  • 3
    I stumbled over `auto&&` vs. _r-value reference_... (not that I'm an expert about that stuff) ...but I believe `auto` with `&&` makes it a universal reference (which is something different). FYI: [auto&& variable's are not rvalue reference](https://stackoverflow.com/q/34899538/7478597) – Scheff's Cat Apr 27 '23 at 09:06
  • 2
    Here is some live demo: https://godbolt.org/z/cv11cj66d. Even though we are iterating over an rvalue array, the forwarding reference `i` becomes an lvalue reference `int&`. Therefore, there is no difference between `auto&&` and `auto&` in this case. In general, look at this post: [What is the advantage of using forwarding references in range-based for loops?](https://stackoverflow.com/q/13130708/580083). – Daniel Langr Apr 27 '23 at 09:16
  • Even temporaries might be modified... – Jarod42 Apr 27 '23 at 14:58
  • @HolyBlackCat omg I meant `std::vector` ... pfff should have checked my question better, now I lost the opportunity of a "new question" attention – Lorah Attkins Apr 27 '23 at 15:05
  • @DanielLangr Ok I guess I get it now. I often see it combined with an `std::move` (to move the individual elements) so I guess in that case it's the same, plain `&` but the `&&` conveys that we are going to modify the element, which would be wrong with `const&`. – Lorah Attkins Apr 27 '23 at 15:11
  • It's worth noting that the excellent answer @DanielLangr linked to has **nothing to do with whether the collection itself is a temporary**. It only is concerned with whether proxy temporaries are generated during the mechanics of iteration. – Ben Voigt Apr 27 '23 at 15:11
  • Furthermore, the type system cannot deduce "single-pass forward iteration, never touch the element again" from the collection being a temporary. Only you know when you're done using any particular element, and then you can `std::move`. – Ben Voigt Apr 27 '23 at 15:13

0 Answers0