我正在学习C ++ 11,我不明白为什么在下面的代码中
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
}
在
行return myNewObject; // Constructor3 gets called here
调用Constructor3。为什么呢?
答案 0 :(得分:3)
您会看到移动构造,因为您的编译器没有执行标准允许的所有优化。
名义上,变量myNewObject
被移动构造到临时值make_x
的返回值,然后将临时值移动分配给x1
。这就是你所看到的。
然而,在这种情况下,标准允许称为“移动构造函数省略”的东西。它与“复制构造函数省略”基本相同,您可能从C ++ 03中熟悉它。这意味着变量myNewObject
和作为make_x
的返回值的临时值可以由编译器转换为单个对象。这只留下了移动任务。
显然你的编译器还没有完成移动操作。
如果您期望的副本,那么原因是一招是,在C ++ 11时,明确要求返回值可享有复制省略(此一个),要移动,而不是复制,其中一个移动是可用的。我记不起参考了,手边没有标准,所以你只需要接受我的话。
答案 1 :(得分:1)
X make_x() // build an X with some data
{
X myNewObject; // Constructor1 gets called here
// fill data..
return myNewObject; // Constructor3 gets called here
}
myNewObject
在此函数范围的末尾被销毁,因此编译器可以通过移动来消除它的内容。