I know that a certain object is only ever created as a temporary object (it’s a private member object within a library). Sometimes, that object is further initialized by chaining member functions together (TempObj().Init("param").Init("other param")). I would like to enable move construction for another object using that temporary instance, and so I was wondering if there was anything incorrect about return std::move(*this).
struct TempObj
{
TempObj &&Member() { /* do stuff */ return std::move(*this); }
};
struct Foo
{
Foo(TempObj &&obj);
};
// typical usage:
Foo foo(TempObj().Member());
Is it functionally equivalent to this?
struct TempObj
{
TempObj(TempObj &&other);
TempObj Member() { /* do stuff */ return *this; }
};
Foo foo(TempObj().Member());
With move semantics, you don’t want (or need) to return r-value references from functions … r-value references are there to “capture” unnamed values or memory addresses. When you return a r-value reference to an object that is in-fact an l-value from the standpoint of the caller, the semantics are all wrong, and you create the opportunity for needless surprises to arise when others are using your object’s methods.
In other words, it would be better to orient your code to look like this:
and have
TempObj::Membersimply return a l-value reference. This makes the move explicit, and there are no suprises involved for someone using your object’s methods.Finally, no, it’s not functionally or semantically equivalent to your last example. There you are actually making a temporary copy of the object, and that copy will be an r-value object (i.e., an unamed object in this scenario) … since the assumption with r-value references is that the object is either an unamed value or object, and it can therefore be harmlessly modified by a function you pass it to that takes an r-value reference argument. On the other-hand, if you’ve passed a copy of an object to a function, then the function cannot modify the original. It will simply modify the referenced temporary r-value, and when the function exits, the temporary r-value copy of the object will be destroyed.