简体   繁体   中英

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?

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 .

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM