鉴于我对返回值优化的理解,我很困惑为什么在下面的示例代码中调用移动构造函数:
#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编译器。
答案 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))
实际上会调用向量的复制构造函数。