【问题标题】:In c++, how to return multiple objects and nevertheless benefit from RVO在 C++ 中,如何返回多个对象并从 RVO 中受益
【发布时间】:2020-05-18 02:43:40
【问题描述】:

我的函数需要返回几个大容器。为了实现这一点,return 语句创建了一个由要返回的容器组成的元组。但是,根据我的测试(使用 Apple clang 版本 11.0.0,clang-1100.0.33.17),可能会在构建元组时制作副本。在调用函数中,返回的元组使用结构化绑定分配给多个变量。

如果我的函数只返回一个容器,则将使用 RVO,并且不会制作副本。当函数返回多个容器时,是否有类似的避免创建副本的好方法?

示例如下:

#include <tuple>
#include <vector>
using namespace std;

tuple<vector<int>, vector<double>> f(){
  vector<int> a(1);
  vector<double> b(1);
  return tuple(a,b);
}

int main(){
  auto [x, y] = f();
}

【问题讨论】:

    标签: c++ rvo


    【解决方案1】:

    如果你尝试移动呢?

    tuple<vector<int>, vector<double>> f(){
      vector<int> a(1);
      vector<double> b(1);
      return tuple(std::move(a), std::move(b));
    }
    

    或者更简单地说,从临时构造元组(这也应该导致移动构造):

    using vector_tuple = tuple<vector<int>, vector<double>>;
    
    vector_tuple f(){
      return std::make_tuple<vector_tuple>(vector<int>(1), vector<double>(1));
    }
    

    【讨论】:

    • 谢谢!我特别喜欢您的第一个解决方案,因为在实际代码中,元组的组成部分不是在同一点创建的。
    【解决方案2】:

    您可以在元组中构建已经存在的向量。

    tuple<vector<int>, vector<double>> f(){
      tuple ret(vector<int>(1), vector<double>(1));
      // Now usable by std::get<N>(ret);
      auto &[a,b] = ret;
      // Now you can use a and b, no copies made.
      return ret;
    }
    

    虽然这与另一个答案非常相似,但我想添加带有结构化绑定的部分,并解释为什么如果您想在没有任何动作的情况下使用 RVO 等,您基本上必须以这种方式或非常相似的方式来完成它。

    对于 RVO,编译器基本上添加了一个不可见的外参数。它在调用时已经为返回的值分配了最终所需的空间,并将位置传递给被调用者。然后被调用者将使用空间来存储返回的变量。因此,对于 RVO,必须在函数中创建返回值,而 RVO 不能执行以下操作:

    std::string foo(int i) {
      std::string ret1{"Hi"};      // Which one should use the space?
      std::string ret2{"Hello"};
      if( i > 0 ) {                // We only know here
        return ret1;
      } else {
        return ret2;
      }
    }
    

    这也是为什么多个返回值在创建时必须属于同一个对象的原因。分配的空间正好适合返回类型,你不能只取两个独立的对象并在这个空间中构造它们,即使你知道它们稍后会在返回的对象中传递。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-04-21
      • 2014-08-02
      • 2017-07-12
      • 2011-03-21
      • 2010-11-06
      • 1970-01-01
      • 2020-12-03
      相关资源
      最近更新 更多