0

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

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

如何在不依赖编译器优化的情况下避免复制向量?

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

(依赖编译器优化对我来说总是很奇怪,因为我应该编写好的、可移植的 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 通过右值引用提供了一些新的“移动”功能。这些能帮上忙吗?

4

2 回答 2

3

据说,C++11 通过右值引用提供了一些新的“移动”功能。这些能帮上忙吗?

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

于 2012-12-04T13:42:30.077 回答
0

一种老式的选择是将向量作为对函数的引用传递,并根据需要进行更改。

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

foo(bar);

另一方面,据我所知,移动语义应该完全符合您的要求,它可能会在不更改您的代码的情况下发生,您可以通过调试器逐步检查它,让我进一步阅读。

编辑:这个问题似乎表明您的原始代码应该自动作为移动操作工作。 这个帖子似乎有更多的信息,但我有点太困了,无法掌握所有内容..

于 2012-12-04T13:28:37.403 回答