2

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

#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 编译器。

4

2 回答 2

1

在您的示例中,您假设将应用 NRVO。但是NRVO只是一种优化,不保证编译器会用到^。

我已经用http://webcompiler.cloudapp.net/测试了你的例子。

默认的编译器选项集有:

/EHsc /nologo /W4

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

Constructor called

Move constructor called

但是,如果启用了适当的优化,例如,/O2标志:

/O2 /EHsc /nologo /W4

然后输出是:

Constructor called

^ 正如@einpoklum 在评论中提到的,自 C++17 以来规则已经改变。

于 2017-03-22T08:20:05.210 回答
1

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

为了看到“更多”的复制省略,您可以尝试发布编译模式。

顺便说一句,inOther.mData没有移动,mData(std::move(inOther.mData))实际上会调用向量的复制构造函数。

于 2017-03-22T08:34:07.833 回答