3

In general I would like to know when and why a modern day compiler, say gcc 4.7 and up using c++11, can not apply an NVRO optimization.

EDIT: I oversimplified this code mistakenly not returning any local variables. A better example was supplied by @cooky451 below see ideone.com/APySue

I saw some snippets of code to answers on other questions that were as such

A f(A&& v)
{
  return v;
}

and they were changed to be

A f(A&& v)
{
  return std::move(v);
}

because they said that the rvalue passed in which is assigned to an lvalue v was still an rvalue and could be moved. However, others wrote that this will remove the ability for NVRO. Wny is this? If the compiler knows that a temporary is being returned can't it construct it directly in place without moving anything? I guess I don't understand why case one would have NVRO but not case 2. I might have the facts wrong hence the question. Also, I read that case 2 was an anti pattern for this reason and that you shouldn't return std::move like this. Any additional insight would be helpful. I was told that behind the scenes the compiler will create something like this below: A& __hidden__ is the assignment to the function, myValue in this case.

A myValue = f(A());

// behind the scenes pseudo code for direct in place construction

void f(A&& v,  A& __hidden__ )
{
    __hidden__ = v;
    return;
}
Deduplicator
  • 44,692
  • 7
  • 66
  • 118
bjackfly
  • 3,236
  • 2
  • 25
  • 38

1 Answers1

1

Both won't use RVO, because it's impossible. The problem is: && is still just a reference. The variable you're returning is not inside your function-local scope! So, without std::move, you'll copy, and with it you'll move. I would advice btw not to expect something per rvalue-reference, as long as you're not writing a move constructor/assignment operator or some perfect-forwarding template-code. Just take it by value. It has a small overhead in some cases, but it's really not going to be significant. And it makes code a lot more readable. And simpler, as the caller can either copy or move the arguments, and you don't have to provide additional const& overloads.

cooky451
  • 3,460
  • 1
  • 21
  • 39
  • Makes sense, I think I over simplified the example. If there was a local stack variable being returned then NVRO should have occurred correct? – bjackfly Sep 07 '13 at 19:38
  • Only in the first case, check https://ideone.com/APySue That's one reason for why using std::move for return values is an anti-pattern; the other one being that move occurs automatically for return if RVO cannot be performed - try it. ;-) Edit: Sometimes std::move for return values can make sense, but those cases are rare. You found one yourself though - when working with references, especially rvalue-references. – cooky451 Sep 07 '13 at 19:43
  • I think that is my main question why can NVRO be applied in the first case and not the second case? Nice example I will play with it to better understand this. – bjackfly Sep 07 '13 at 19:48
  • RVO is probably not applied because std::move (http://en.cppreference.com/w/cpp/utility/move) actually returns a reference. – cooky451 Sep 07 '13 at 19:50
  • So if I was just doing return A(77) from the foo() it seems it would be able to optimize with RVO. So is it because the move is creating a reference to an rvalue instead of an rvalue itself that it can't perform this? I believe this is what you are saying. – bjackfly Sep 07 '13 at 20:25
  • One last question. You said "move occurs automatically for return if RVO cannot be performed - try it. " So if I turned off RVO ( not sure what switch that is ) would your original foo method perform a move instead of a copy on the return? It seems like it would be a copy? – bjackfly Sep 07 '13 at 20:30
  • Yes, my foo() function would move. Easy to show by making RVO too hard: https://ideone.com/6BrPGj – cooky451 Sep 07 '13 at 20:33
  • Nice, I got the same behavior using the compile switch for gcc -fno-elide-constructors on the original but your new function even explains more about how RVO can be too hard for the compiler to figure out. Awesome help! – bjackfly Sep 07 '13 at 20:37