odinthenerd
odinthenerd

Reputation: 5552

Why is the destructor called before the move constructor when returning a temporary (rvalue)

I suspect I don't understand something about move semantics. Given the following code I would expect the debugger (MSVC2010SP1) to call Proxy's members in the following order:

Instead the order is:

This makes no sense to me. What I'm trying to do is track the lifetime of the proxy class passing the job of closing the resource via the move constructor from one object to another.

Upvotes: 2

Views: 1620

Answers (2)

Joseph Mansfield
Joseph Mansfield

Reputation: 110668

Returning by rvalue reference doesn't actually cause anything to be moved. It just returns by reference. However, it's different to returning an lvalue reference because an expression calling a function that returns an rvalue reference is an xvalue (as opposed to an lvalue). The xvalue (as a subset of rvalue expressions) can then be moved from. If you wanted to move from the returned object of a function returning lvalue reference, you would have to use std::move to make it an rvalue.

You very rarely will want to actually return an rvalue reference. The only vaguely common use for it is to allow a private member of an object to be moved from. If you want an object to be moved when you return it from a function, just return it by value. In your case, if the return type of getProxy was just Proxy, the temporary would be moved from into the returned object and then that would be moved from into p (save for any elision).

As you have it, your temporary object (contructed by Proxy(this)) is destroyed at the end of the return statement - this is the first call of the destructor. The returned reference is now referencing an invalid object and p is constructed by moving from this invalid reference. That gives you undefined behaviour.

Upvotes: 2

getProxy() returns a reference to a temporary, which goes out of scope at function end and results in a dangling reference.

Upvotes: 6

Related Questions