我一直在测试rvalue引用并移动语义,并希望确保我理解何时应该省略副本以及何时应该遵循移动语义.
鉴于以下内容
class NRVCA
{
public:
NRVCA(int x):
{}
NRVCA(const NRVCA & Rhs)
{}
NRVCA& operator=(const NRVCA& dref)
{}
};
NVCRA GetATemp()
{
return NVCRA(5);
}
NVCRA GetACopy()
{
NVCRA ret(5);
...
return ret;
}
int main()
{
//This call will be elided allays and invoke the single param constructor
NVCRA A = GetATemp();
//This call will be a traditional copy the complier may elide this
// if so the work will be done inline
NVCRA B = GetACopy();
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,移动语义不起作用,与c ++ 11中C++ 03的唯一区别在于,而不是编译器被允许忽略它们需要忽略.
问题1.在什么情况下,我保证复制构造函数将会或不会被删除.
问题2.有没有办法强制编译器不要忽视.
问题3.假设您具有逻辑上一致的复制操作,是否有任何逻辑上的原因我不希望编译器这样做.
问题4.如果我定义了移动构造函数,则无论如何都不会删除副本.这应该影响我的课程设计.
消除副本和移动始终是可选的优化,标准不保证何时完成.Elision与选择移动复制的编译器不同.当根据其正常的重载决策规则选择移动构造或移动分配时,语言保证.
一些编译器提供了一个标志来关闭elision.gcc和clang有-fno-elide-constructors.MSVC没有特定的选项,但是禁用优化可能会避免某些缺陷(但有些不能被关闭,例如副本Foo x = 1;)
我不知道有什么理由不在生产版本中删除副本/移动.
有些人建议在返回'重'级时不要依赖'返回值优化',因为RVO不能保证.就个人而言,我刚刚验证了我的编译器对它的了解并继续进行.现在可以移动对象,您不再需要担心编译器是否支持这样的优化,因为即使它不支持,您仍然会获得移动而不是副本.