了解关于c ++ 11的遵守规则

rer*_*run 4 c++ c++11

我一直在测试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.如果我定义了移动构造函数,则无论如何都不会删除副本.这应该影响我的课程设计.

bam*_*s53 7

  1. 消除副本和移动始终是可选的优化,标准不保证何时完成.Elision与选择移动复制的编译器不同.当根据其正常的重载决策规则选择移动构造或移动分配时,语言保证.

  2. 一些编译器提供了一个标志来关闭elision.gcc和clang有-fno-elide-constructors.MSVC没有特定的选项,但是禁用优化可能会避免某些缺陷(但有些不能被关闭,例如副本Foo x = 1;)

  3. 我不知道有什么理由不在生产版本中删除副本/移动.

  4. 有些人建议在返回'重'级时不要依赖'返回值优化',因为RVO不能保证.就个人而言,我刚刚验证了我的编译器对它的了解并继续进行.现在可以移动对象,您不再需要担心编译器是否支持这样的优化,因为即使它不支持,您仍然会获得移动而不是副本.