从函数返回时避免复制 - 不依赖于编译器优化

时间:2012-12-04 13:13:50

标签: c++

在这段代码中,一个巨大的向量可以(取决于编译器)在返回时复制:

vector<string> foo() {
  vector<string> vec;
  //make vec huge
  return vec;
}
vector<string> bar = foo();

如何避免复制矢量,而不依赖于编译器优化

现在,请理解这只是一个简单的例子,只有一个return语句。但对于更复杂的情况,即使是优秀的编译器也不可能进行优化以避免复制向量。 (This answer对另一个问题提到了一个这样的案例。)

(首先依赖于编译器优化对我来说似乎总是很奇怪,因为我应该写好的,可移植的,C ++代码,而不是担心这个和那个编译器做了一些事情。所有那些“编译器优化”对其他问题的回答因此困扰我。)

到目前为止我提出的一个想法是使用C ++ 11的智能指针:

shared_ptr<vector<string>> foo() {
  shared_ptr<vector<string>> vec_ptr = make_shared<vector<string>>();
  //make *vec_ptr (i.e. the actual vector) huge
  return vec_ptr;
}
shared_ptr<vector<string>> bar_ptr = foo();
//now, *bar_ptr is the underlying vector we can use

看起来这样可以避免所有情况下的副本。问题是这段代码变得非常麻烦。

任何好的非繁琐的替代方案?据推测,C ++ 11通过右值引用提供了一些新的“移动”功能。那些帮助吗?

2 个答案:

答案 0 :(得分:3)

  

据说,C ++ 11提供了一些新的“移动”功能   右值参考。那些帮助吗?

是的,如果编译器因任何原因不使用RVO,那么它将在这种情况下使用移动,因为std :: vector有一个移动运算符,并且在返回这样的单个变量时它是适用的。当使用c ++ 11编译器进行编译而没有任何更改时,您的原始代码应该执行此操作。

答案 1 :(得分:0)

一个老派选项是传递向量作为对函数的引用并根据需要进行更改。

void foo(vector<string> &vec){
...

foo(bar);

另一方面,移动语义,因为我知道它应该完全按照您的意愿执行,它可能在没有对代码进行任何更改的情况下发生,您可以通过使用调试器来检查它,让我进一步阅读。

编辑:This question似乎表明您的原始代码应该自动作为移动操作。 This Post似乎有更多的信息,但我有点太困,无法掌握一切......