3
votes

I would like to know if my assumption is correct -> Rvalue references work just like lvalue references except that they can only bind to rvalues and hence they can be used for detecting rvalues.

So when used as return type, it works just like lvalue references, like they are returning the actual object they are bound to.

When used as parameter type, they pass values without any copying.

I see a lot of people asking what the difference is between returning by rvalue reference and by value(and by lvalue reference), but couldn't they all be answered by saying that rvalue references works like lvalue references, so if you know what happens when using lvalue references, you probably know what happens when using rvalue references, i.e. you would know that returning by rvalue reference returns the actual object while returning by value returns a copy, just like the difference between returning by lvalue reference and by value(roughly)?

Or am I wrong?

2
I think that's a fine digest. - Quentin
It's not clear to me if you realise that returning a reference (lvalue or rvalue) to a local (stack) variable will return a dangling reference, leading to undefined behaviour. - Richard Critten
returning an r-value reference prevents RVO and is therefore a pessimisation (as well as being potentially dangerous) - Richard Hodges
@RichardCritten, I know :) That also makes much sense if the local object has automatic storage and would have been destroyed at the return statement. - user8221510
@RichardHodges I think you're assuming that the function is returning a local variable. If the function is returning a reference to an input or to a member variable (if it's an object method), then r-value reference can be the fastest, though still potentially dangerous. - Nir Friedman

2 Answers

1
votes

When any named object is written to, it's treated as its real type.

When any object is read, it's treated as an l-value reference.

An object returned from a function does not have a name, so it's treated as its real type.

Everything else follows from that.

-1
votes

As far as using rvalue references as return types, it is generally similar to lvalue references, i.e. you usually shouldn't do it, since you can't return a reference to a local variable. However, the combination of rvalue references in inputs and outputs enables some interesting things:

Matrix operator+(const Matrix& lhs, const Matrix& rhs) {
    auto r = lhs;
    r += rhs;
    return r;
}

A typical signature for some matrix addition function. But exploiting rvalue references, we can start adding overloads like this:

Matrix&& operator+(Matrix&& lhs, const Matrix& rhs) {
    lhs += rhs;
    return lhs;
}

The second version is neat because there are no copies, and not even any moves! This isn't really doable with lvalue references because you can't be sure you can just go ahead and use/abuse the storage of an input. So rvalue references do open up some new opportunities to return by reference, but it's still the exception rather than the norm.