返回值优化vs auto_ptr用于大向量

时间:2012-05-04 13:33:28

标签: c++ auto-ptr rvo

如果我使用auto_ptr作为填充大型向量的函数的返回值,则会使该函数成为源函数(它将创建内部auto_ptr并在返回非const auto_ptr时传递所有权)。但是,我不能将此函数与STL算法一起使用,因为为了访问数据,我需要对auto_ptr进行解除引用。我猜的一个很好的例子是大小为N的向量场,每个向量有100个分量。如果N很大,则函数返回每个100分量向量的值或者ref不相同。

另外,当我尝试这个非常基本的代码时:

class t
{
    public: 
         t() { std::cout << "ctor" << std::endl; }
         ~t() { std::cout << "dtor" << std::endl; }
};

t valueFun()
{
   return t();
}

std::auto_ptr<t> autoFun()
{
   return std::auto_ptr(new t());
}

autoFun和fun调用都会产生输出

CTOR 析构函数

所以我实际上看不到正在创建的自动变量被传递给return语句。这是否意味着为valueFun调用设置了返回值优化?在这种情况下,valueFun是否会创建两个自动对象?

如何使用函数优化如此大型数据结构的总体?

2 个答案:

答案 0 :(得分:4)

有很多选择,动态分配可能不是最好的。


在我们讨论这个讨论之前:这是一个瓶颈吗?

如果你没有分析并确保它是一个瓶颈,那么这个讨论可能完全没有了......记住,比分析调试版本几乎没用。


现在,在C ++ 03中有几个选项,从最可口的到最少的一个:

  • 信任编译器:例如,即使在gcc的Debug版本中,未命名的变量也使用RVO。
  • 使用“out”参数(通过引用传递)
  • 在堆上分配并返回指针(智能与否)
  • 检查编译器输出

就个人而言,除非剖析器证明我错了,否则我会相信我的编译器。

在C ++ 11中,移动语义有助于我们更加自信,因为每当有return语句时,如果RVO无法启动,则可以自动使用移动构造函数(如果可用);并且在vector上移动构造函数很便宜。

所以它变成了:

  • 信任编译器:RVO或移动语义
  • 在堆上分配并返回unique_ptr

但实际上第二点应仅用于移动语义无用的少数类:移动语义的成本通常与sizeof的返回成比例,例如std::array<T,10>大小等于10*sizeof(T)所以它不太好,可能会从堆分配+ unique_ptr中受益。


Tangent:你已经信任你的编译器了。你相信它会警告你有关错误的信息,你相信它会警告你关于危险/可能不正确的结构,你相信它能正确地将你的代码转换成机器组装,你相信它可以应用有意义的优化来获得一个体面的加速...不信任编译器在明显的情况下应用RVO就像不信任你的心脏外科医生10美元的账单:这是你最不担心的。 ;)

答案 1 :(得分:1)

我很确定编译器会为valueFun执行返回值优化。编译器无法应用返回值优化的主要情况是:

  • 返回参数
  • 根据条件
  • 返回不同的对象

因此auto_ptr不是必需的,并且由于必须使用堆而更慢。

如果您仍然担心移动这么大的向量的成本,您可能希望使用移动语义(C {+ std::vector aCopy(std::move(otherVector)))。这几乎与RVO和可以在任何地方使用(当RVO无法使用时,它也可以保证用于返回值。)

我相信大多数现代编译器此时支持移动语义(或技术上的右值引用)