避免从函数返回时进行复制,而不依赖编译器优化

Avoiding copying upon returning from a function - without relying on compiler optimizations

本文关键字:依赖 优化 编译器 复制 函数 返回      更新时间:2023-10-16

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

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通过右值引用提供了一些新的"移动"功能。这些能帮上忙吗?

据推测,C++11通过右值引用。这些能帮上忙吗?

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

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

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

另一方面,根据我的理解,移动语义应该完全按照你的意愿进行,它可能会在不对代码进行任何更改的情况下发生,你可以通过使用调试器来检查它,让我进一步阅读。

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