C ++ 11为什么在返回临时对象之前调用move构造函数

时间:2013-03-30 12:26:15

标签: c++ c++11

我正在学习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。为什么呢?

2 个答案:

答案 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在此函数范围的末尾被销毁,因此编译器可以通过移动来消除它的内容。