Joe Joe
Joe Joe

Reputation: 121

Understanding rvalue reference on return

For example i have code such as below

//g++  5.4.0

#include <iostream>

struct data
{
    int n;
    data()
    {
        std::cout << "data()\n";
    }
    data(const data&)
    {
        std::cout << "data(const data&)\n";
    }
    data(data&&)
    {
        std::cout << "data(data&&)\n";
    }
};

class container
{
    data d;    
public:
    data getData()
    {
        return std::move(d);
    }
};

int main()
{
    container c;
    data result = c.getData();
}

And output is:

data() 
data(data&&)

I don't understand how it works. I have not declared return type as data&&, but move constructor works fine for result. Yes, code is std::move(d) but return type is not data&&. So, how does it work?

Upvotes: 2

Views: 92

Answers (2)

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275350

This answer changes in .

data getData()
{
    return std::move(d);
}

This method moves d into its return value.

data x = foo.getData();

this one constructs x from the return value of getData. However the C++ standard encourages and permits this construction to be elided if getData returns a prvalue (a value type that matches). Elision means that the identity and lifetime of the return value and x are merged. Only one object exists, not two.

This permits skipping side effects, like print statements in move constructors.

So d is the object moved from, and that move directly constructs x.

If you change getData to return data&&, now no move is done withingetData but one is done outside when you construct x.

In the return value of getData is never an object, it is a prvalue, and prvalues in are more like instructions to create objects. In effect elision is no longer optional.

Upvotes: 4

Edy
Edy

Reputation: 470

If the return type is set to data (as in your case), then the returned object is a prvalue. If the return type is set to data&&, then the returned object is an xrvalue.

In either case, the returned object is an rvalue, and result's move constructor will be called.

See also: http://stackoverflow.com/a/10159163/4509057

Upvotes: 3

Related Questions