Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between returning a const reference and rvalue reference

If I'm not wrong, I think that both a const reference and a rvalue reference can bind to a rvalue. Is there any practical difference between a function that returns the former and a function that returns the latter?

EDIT. I cannot modify the former, but why would I be interested in modifying a rvalue? Does it make sense?

like image 904
jbgs Avatar asked Mar 28 '13 12:03

jbgs


People also ask

Can a const function return a reference?

If the thing you are returning by reference is logically part of your this object, independent of whether it is physically embedded within your this object, then a const method needs to return by const reference or by value, but not by non-const reference.

What is the difference between lvalue and rvalue references?

An lvalue is an expression that yields an object reference, such as a variable name, an array subscript reference, a dereferenced pointer, or a function call that returns a reference. An lvalue always has a defined region of storage, so you can take its address. An rvalue is an expression that is not an lvalue.

What is an rvalue reference?

Rvalue references is a small technical extension to the C++ language. Rvalue references allow programmers to avoid logically unnecessary copying and to provide perfect forwarding functions. They are primarily meant to aid in the design of higer performance and more robust libraries.

Can a function return an rvalue?

Typically rvalues are temporary objects that exist on the stack as the result of a function call or other operation. Returning a value from a function will turn that value into an rvalue. Once you call return on an object, the name of the object does not exist anymore (it goes out of scope), so it becomes an rvalue.


2 Answers

A const lvalue reference can bind to anything. An rvalue reference can only bind to non-const rvalues.

            non-const lvalue   const lvalue   non-const rvalue   const rvalue
const T&    yes                yes            yes                yes
T&&         no                 no             yes                no

As you can see, they are very different.

In addition, if a function call returns an lvalue reference, that expression is an lvalue, but if a function call returns an rvalue reference to object, that expression is an xvalue.

A function call is an lvalue if the result type is an lvalue reference type or an rvalue reference to function type, an xvalue if the result type is an rvalue reference to object type, and a prvalue otherwise.

As for when you would want to modify an rvalue - well this is precisely what move semantics are all about. Consider the following function call:

void func(std::string);

func(std::string("Hello"));

The expression std::string("Hello") is an rvalue that creates a temporary object. When initializing the std::string parameter with this rvalue, it will choose the constructor that takes an rvalue reference - the move constructor. This constructor then steals things from the rvalue, which is typically much faster than doing a full copy. We can steal from it because we know it's temporary.

As for when you should return const lvalue references or rvalue references:

  • Returning a const lvalue reference is most commonly used when you want to give access to read an "internal" object (perhaps a member of a class), but not allow people to modify it.

  • Returning an rvalue reference is most commonly used (not common at all) when you want to allow calling code to move from an "internal" object (perhaps a member of a class). So instead of moving from a temporary returned object (as they would when returning by value), they literally move from the internal object.

    This could also be achieved with a non-const lvalue reference, but then they would have to explicitly std::move it.

So it's not very likely that you'll need to return an rvalue reference.

Not that std::forward has a return type that looks like T&&. However, this is deceptive, because it may or may not be an rvalue reference depending on the type of T. See universal references.

like image 146
Joseph Mansfield Avatar answered Sep 23 '22 02:09

Joseph Mansfield


Is there any practical difference between a function that returns the former and a function that returns the latter?

The question seems to be ill-formed. A function that returns a constant lvalue-reference provides access to an object only for reading, while a function that returns an rvalue-reference provides access for moving which means that the caller can take the contents of the referred object and move it to a different object. They are not comparable by any means.

In both cases, the references must point to an object whose lifetime spans beyond the end of the function that is returning it, as otherwise the caller will trip with undefined behavior on using that reference.

like image 44
David Rodríguez - dribeas Avatar answered Sep 21 '22 02:09

David Rodríguez - dribeas