views:

547

answers:

4

for example:

Beta_ab&&
Beta::toAB() const {
    return move(Beta_ab(1, 1));
}
A: 

First, as economists would ask - more efficient than what?

Don't you have a double indirection here, which is less efficient than a single one (which in turn is more efficient than returning a constructed object, albeit sometimes you have to)?

Ariel
Double indirection?
avakar
avakar
I see now - didn't follow the new standard enough. Hence, I intepreted it as ref-to-ref... Apologies ☺
Ariel
+2  A: 

Return by rvalue reference will be more efficient if the copy operation for an object is expensive and the move operation is able to avoid copying some of the state of an object.

Michael Burr
+2  A: 

It allows you to return a temporary directly, without having to copy it. Which means that yes, it will be faster than copying the temporary and returning the copy.

It doesn't make sense to ask if it is "more efficient" though. More efficient than what? Not having to do a copy is certainly faster than having to do a copy, but sometimes, you may have been able to avoid the function call entirely, and then that would have been more efficient. Sometimes, you may have to do the copy anyway, and then it won't make a difference.

One of the main reasons why rvalue references were added is performance. So yes, it can potentially improve performance. If you use it in a context where it makes sense.

jalf
+13  A: 
Beta_ab&&
Beta::toAB() const {
    return move(Beta_ab(1, 1));
}

This returns a dangling reference, just like with the lvalue reference case. After the function returns, the temporary object will get destructed. You should return Beta_ab by value, like the following

Beta_ab
Beta::toAB() const {
    return Beta_ab(1, 1);
}

Now, it's properly moving a temporary Beta_ab object into the return value of the function. If the compiler can, it will avoid the move altogether, by using RVO (return value optimization). Now, you can do the following

Beta_ab ab = others.toAB();

And it will move construct the temporary into ab, or do RVO to omit doing a move or copy altogether. I recommend you to read BoostCon09 Rvalue References 101 which explains the matter, and how (N)RVO happens to interact with this.


Your case of returning an rvalue reference would be a good idea in other occasions. Imagine you have a getAB() function which you often invoke on a temporary. It's not optimal to make it return a const lvalue reference for rvalue temporaries. You may implement it like this

struct Beta {
  Beta_ab ab;
  Beta_ab const& getAB() const& { return ab; }
  Beta_ab && getAB() && { return move(ab); }
};

Note that move in this case is not optional, because ab is neither a local automatic nor a temporary rvalue. Now, the ref-qualifier && says that the second function is invoked on rvalue temporaries, making the following move, instead of copy

Beta_ab ab = Beta().getAB();
Johannes Schaub - litb
I had always assumed the dangling reference problem went away automagically when the return type was an r-value reference. Glad I got that straighted out before it bit me. Stack smashing bugs suck.
caspin
:) Really, rvalue references are "just references" like lvalue references are. they don't copy or store anything.
Johannes Schaub - litb