Reputation: 13427
I'm studying C++11 and I don't understand why in the following code
class X
{
std::vector<double> data;
public:
// Constructor1
X():
data(100000) // lots of data
{}
// Constructor2
X(X const& other): // copy constructor
data(other.data) // duplicate all that data
{}
// Constructor3
X(X&& other): // move constructor
data(std::move(other.data)) // move the data: no copies
{}
X& operator=(X const& other) // copy-assignment
{
data=other.data; // copy all the data
return *this;
}
X& operator=(X && other) // move-assignment
{
data=std::move(other.data); // move the data: no copies
return *this;
}
};
X make_x() // build an X with some data
{
X myNewObject; // Constructor1 gets called here
// fill data..
return myNewObject; // Constructor3 gets called here
}
int main()
{
X x1;
X x2(x1); // copy
X x3(std::move(x1)); // move: x1 no longer has any data
x1=make_x(); // return value is an rvalue, so move rather than copy
}
in the line
return myNewObject; // Constructor3 gets called here
the Constructor3 gets called. Why?
Upvotes: 4
Views: 528
Reputation: 279285
You see a move construction because your compiler is not doing all the optimization that it is permitted to by the standard.
Nominally, the variable myNewObject
is move-constructed to the temporary that is the return value of make_x
, and then the temporary is move-assigned to x1
. This is what you're seeing.
However, in this case the standard permits something called "move constructor elision". It's basically the same thing as "copy constructor elision", which might be familiar to you from C++03. It means that the variable myNewObject
and the temporary that is the return value of make_x
can be transformed by the compiler into a single object. That leaves just the move assignment.
Apparently your compiler has not done the move elision.
If you expected a copy, then the reason it's a move is that in C++11, a return value that is eligible for copy elision (which this one is), is explicitly required to be moved rather than copied where a move is available. I can't remember the reference, and don't have the standard on hand, so you'll just have to take my word for it.
Upvotes: 3
Reputation: 63220
X make_x() // build an X with some data
{
X myNewObject; // Constructor1 gets called here
// fill data..
return myNewObject; // Constructor3 gets called here
}
myNewObject
gets destroyed at the end of this function scope, so its ok for the compiler to rip its guts out with a move.
Upvotes: 1