Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return value or rvalue reference?

In Scott Meyer's new book, he proposes an example usage for rvalue reference qualifiers that looks something like this:

class Widget {
private:
    DataType values;

public:
    DataType& data() &  { return values; } 
    DataType  data() && { return std::move(values); } // why DataType?
};

So that:

auto values = makeWidget().data();

move-constructs values instead of copy-constructing it.

Why does the rvalue-ref-qualified data() return DataType instead of DataType&&? auto would still deduce DataType in that case (although decltype(auto) wouldn't - but that can't be the only reason to prefer to return a value instead of an ravlue ref). This highly voted answer returns an rvalue ref, which makes more sense conceptually to me.

like image 618
Barry Avatar asked Dec 08 '14 22:12

Barry


1 Answers

DataType data() && { return std::move(values); } // why DataType?

auto values = makeWidget().data();

The temporary that holds the return value will be initialized through the move-constructor, copy-initialized from move(values).

Then that temporary initializes values, but since makeWidget().data() is an rvalue (prvalue to be precise) the move-constructor is called again - with the temporary as its argument.

Now consider copy-elision:

When a nameless temporary, not bound to any references, would be moved or copied into an object of the same cv-unqualified type, the copy/move is omitted. When that temporary is constructed, it is constructed directly in the storage where it would otherwise be moved or copied to. When the nameless temporary is the argument of a return statement, this variant of copy elision is known as RVO, "return value optimization".

So the second move will (presumably) be completely elided, and only one is left - the one we would have had anyway, had the return type been the rvalue reference.

The problem with returning an rvalue reference is that if we write

auto&& values = makeWidget().data();

values will be dangling as binding an xvalue to a reference doesn't extend anythings lifetime. When we return the object type, the temporaries lifetime is extended.

like image 56
Columbo Avatar answered Oct 20 '22 03:10

Columbo