为什么要调用移动构造函数?

时间:2017-03-22 07:50:38

标签: c++ c++11 move-constructor rvo

鉴于我对返回值优化的理解,我很困惑为什么在下面的示例代码中调用移动构造函数:

#include <vector>
#include <iostream>

class MyCustomType
{
public:
  MyCustomType()
  {
    std::cout << "Constructor called" << std::endl;
  }

  MyCustomType(const MyCustomType & inOther) : // copy constructor
    mData(inOther.mData)
  {
    std::cout << "Copy constructor called" << std::endl;
  }

  MyCustomType(MyCustomType && inOther) : // move constructor
    mData(std::move(inOther.mData))
  {
    std::cout << "Move constructor called" << std::endl;
  }

private:
  std::vector<int> mData;
};

MyCustomType getCustomType()
{
  MyCustomType _customType;
  return _customType;
}

int main()
{
  MyCustomType _t = getCustomType();
}

输出:

Constructor called
Move constructor called

我假设只有一个MyCustomType实例被构造并直接分配给_t

有关信息,我使用的是VC14编译器。

2 个答案:

答案 0 :(得分:1)

在您的示例中,您假设将应用NRVO。但是NRVO只是一个优化,它不能保证编译器使用^。

我已使用http://webcompiler.cloudapp.net/测试了您的示例。

默认的编译器选项集是:

/EHsc /nologo /W4

在这种情况下,输出与您的输出类似:

Constructor called

Move constructor called

但是,如果使用/O2 flag:

启用了适当的优化
/O2 /EHsc /nologo /W4

然后输出是:

Constructor called

^正如@einpoklum在评论中提到的那样,自C ++ 17以来规则发生了变化。

答案 1 :(得分:1)

因为表达式getCustomType()prvalue(rvalue),并且参数可以比参数更符合cv。

为了看到更多&#34;复制elision,你可以尝试发布编译模式。

BTW,inOther.mData未被移动,mData(std::move(inOther.mData))实际上会调用向量的复制构造函数。