代码之家  ›  专栏  ›  技术社区  ›  Roman

return语句中对象构造时的std::move()会帮助还是阻止RVO?[副本]

  •  -3
  • Roman  · 技术社区  · 9 年前

    由于来自社区的广泛响应,我这样问是为了揭穿堆栈溢出用户针对实现的响应。

    以下哪项是最佳实践(提供了最大的优化)?

    // version 1
    MyObject Widget::GetSomething() {
      return MyObject();
    }
    
    // version 2
    MyObject Widget::GetSomething() {
      return std::move(MyObject());
    }
    
    // version 3
    MyObject Widget::GetSomething() {
      auto obj = MyObject()
      return obj;
    }
    
    // version 4
    MyObject Widget::GetSomething() {
      auto obj = MyObject()
      return std::move(obj);
    }
    

    谢谢你对雅克的直接、恭敬的回答。[接受答案]

    1 回复  |  直到 9 年前
        1
  •  2
  •   Community Mohan Dere    6 年前
    // version 1
    MyObject Widget::GetSomething() {
      return MyObject();
    }
    

    在C++03中,这需要 MyObject 可复制。在运行时,不会使用任何具有合理设置的“真实”编译器进行复制,因为标准允许在此省略。

    在C++11或14中,它要求对象是可移动或可复制的。省略仍然存在;未进行移动或复制。

    在C++17中,这里没有移动或复制到elide。

    在任何情况下,在实践中,

    // version 2
    MyObject Widget::GetSomething() {
      return std::move(MyObject());
    }
    

    这在C++03中无效。

    在C++11及更高版本中, 我的对象

    // version 3
    MyObject Widget::GetSomething() {
      auto obj = MyObject();
      return obj;
    }
    

    与版本1相同,只是C++17的行为类似于C++11/14;看似无害的更改可能会迫使编译器实际移动 obj

    // version 4
    MyObject Widget::GetSomething() {
      auto obj = MyObject();
      return std::move(obj);
    }
    

    在实践中,这与版本2的行为类似。在构造时会发生额外的移动(在C++03中复制) obj公司 但它被省略了,所以在运行时不会发生任何事情。

    1和3都将编译为相同的运行时代码。3稍微更脆弱。

    1>=3>=2>=4 实际上是从快到慢的顺序,其中“更脆弱”的代码在其他方面是相同的速度 <= .

    作为一个可能使3比1慢的示例,如果您有if语句:

    // version 3 - modified
    MyObject Widget::GetSomething() {
      auto obj = MyObject();
      if (err()) return MyObject("err");
      return obj;
    }
    

    突然间,许多编译器将被迫移动 转换为返回值,而不是删除 obj公司