c++ - 理解关于 c++11 的省略规则

标签 c++ c++11

我一直在测试右值引用和移动语义,并希望确保我了解何时应删除拷贝以及何时应遵循移动语义。

鉴于以下

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();

}

在这种情况下,移动语义不起任何作用,与 C++11 中的 C++03 的唯一区别在于,编译器不被允许省略,而是需要省略。

所以 问题 1. 在什么情况下我保证复制构造函数会或不会被省略。

问题2.有没有办法强制编译器不省略

问题 3。假设您有逻辑上一致的复制操作,是否有任何合乎逻辑的理由说明我不希望编译器这样做。

问题 4. 如果我定义了一个移动构造函数,那么在拷贝没有被省略的情况下,移动将会发生。这是否会影响我的类(class)设计。

最佳答案

  1. 省略复制和移动始终是可选的优化,标准不保证何时完成。 Elision 不同于编译器选择 move over copy。当根据其正常的重载决议规则选择移动构造或移动赋值时,语言保证。

  2. 一些编译器提供了一个标志来关闭省略。 gcc 和 clang 有 -fno-elide-constructors。 MSVC 没有特定的选项,但禁用优化可能会避免一些省略(但有些无论如何都无法关闭,例如 Foo x = 1; 中的拷贝)

  3. 我不知道有什么理由不在生产构建中删除拷贝/移动。

  4. 有些人建议在返回“重”类时不要依赖“返回值优化”,因为不能保证 RVO。就我个人而言,我只是验证了我的编译器是否擅长它并继续它。现在可以移动对象,您不再需要担心编译器是否支持此类优化,因为即使它不支持,您仍然会移动而不是复制。

关于c++ - 理解关于 c++11 的省略规则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9267687/

相关文章:

c++ - 使用 msxml 解析器验证 xml 模式

c++ - QT & C++ : Passing 'const QString' discards qualifiers

c++ - 如何访问图像上 2 个非线性点之间的所有像素

c++ - 为什么 std::move() 在 C++ 中工作?

c++ - 使用模板访问成员变量

c++ - 断言:指针必须来自 'local' 堆

c++ - xcode apple clang 独有的 make_shared 的奇怪 stdlib(memory.h) 问题

c++ - std::invoke 没有匹配的重载函数发现 VS 2015 中给出的错误

c++ - 我们是否应该在大型 std::vector 中存储指向类实例的智能指针以获得更好的性能?

C++11:有没有办法强制类只能用作右值?