C++ 大向量的返回值优化与自动ptr

C++ 大向量的返回值优化与自动ptr,c++,auto-ptr,rvo,C++,Auto Ptr,Rvo,如果我使用auto_ptr作为填充大向量的函数的返回值,这将使该函数成为源函数(它将创建一个内部auto_ptr,并在返回非常量auto_ptr时传递所有权)。但是,我不能在STL算法中使用此函数,因为为了访问数据,我需要消除自动ptr的差异。我想一个很好的例子是一个大小为N的向量场,每个向量有100个分量。如果N较大,则函数按值或按ref返回每个100分量向量的方式不相同 另外,当我尝试以下非常基本的代码时: class t { public: t() { std:

如果我使用auto_ptr作为填充大向量的函数的返回值,这将使该函数成为源函数(它将创建一个内部auto_ptr,并在返回非常量auto_ptr时传递所有权)。但是,我不能在STL算法中使用此函数,因为为了访问数据,我需要消除自动ptr的差异。我想一个很好的例子是一个大小为N的向量场,每个向量有100个分量。如果N较大,则函数按值或按ref返回每个100分量向量的方式不相同

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

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());
}
t类
{
公众:

t(){std::cout我相当确信编译器将为valueFun进行返回值优化。编译器无法应用返回值优化的主要情况有:

  • 返回参数
  • 根据条件返回不同的对象
因此,auto_ptr是不必要的,并且由于必须使用堆,因此速度会更慢

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


我相信现在大多数现代编译器都支持移动语义(技术上说是右值引用)

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


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

如果您没有评测并确保它是一个瓶颈,那么这个讨论可能会完全结束……记住,评测调试构建是非常无用的


现在,在C++03中有几个选项,从最美味的到最不美味的:

  • 信任编译器:例如,即使在gcc中的调试构建中,未命名变量也会使用RVO
  • 使用“out”参数(通过引用传递)
  • 在堆上分配并返回指针(智能或非智能)
  • 检查编译器输出
就个人而言,除非剖析器证明我错了,否则我会相信我的编译器

在C++11中,移动语义帮助我们变得更加自信,因为每当出现
return
语句时,如果RVO无法启动,那么可以自动使用移动构造函数(如果可用);并且
vector
上的移动构造函数非常便宜

因此,它变成:

  • 信任编译器:RVO或move语义
  • 在堆上分配并返回一个
    unique\u ptr
但实际上,第二点应该只用于移动语义没有多大帮助的少数类:移动语义的代价通常与
sizeof
的返回成正比,例如
std::array
的大小等于
10*sizeof(T)
所以它不是很好,可能会从堆分配+
unique\u ptr
中受益



Tangent:你已经信任你的编译器了。你相信它会警告你错误,你相信它会警告你危险/可能不正确的构造,你相信它会正确地将你的代码翻译成机器程序集,你相信它会应用有意义的优化来获得适当的速度…不相信编译器会在明显的ca中应用RVOses就像一张10美元的钞票不信任你的心脏外科医生:这是你最不担心的事

你是在问RVO是否也适用于大向量吗?如果是,你就不能用上面的例子来测试它吗?当我测试它时,这是否意味着它适用于所有编译器/平台?我怎么知道包含RVO,我应该阅读编译器规范吗?如果代码是在HPC集群上编译的,具有不同的是的,我明白你的意思。这是编译器允许但不需要做的事情之一,所以你永远不能确定。顺便问一下,你有C++11支持吗?相当肯定(从我的角度来看,如果我要在100个内核上运行这个东西,并且如果它会随着时间的推移而增长,我需要100%确定代码的功能。非常感谢这一点!)