【问题标题】:Is returning a vector slower than passing by reference?返回向量是否比通过引用传递慢?
【发布时间】:2018-07-27 04:53:15
【问题描述】:

在过去,我们被训练使用通过引用传递的结果参数,以避免不必要地复制数据。

但是对于更智能的编译器 - 尤其是对 C++11 的扩展这仍然需要吗?

具体来说,2018 年有什么理由让现代 C++11/C++14 编译器(仍然)使用

void Filter(vector<CObject*> &elements, vector<CObject*> &outElements);

而不是简单地返回向量,即

vector<CObject*> Filter(vector<CObject*> &elements);

提前感谢所有见解!

【问题讨论】:

  • 即使在 C++98 中也从不需要复制,但 RVO 过去是并且仍然是可选的。 C++17 引入了一些强制复制省略的情况,但这不包括 RVO。现在大多数编译器都这样做了,所以我认为你可以依赖它,特别是如果它使代码更干净的话。
  • @Ivan C++ introduces some cases when copy elision is mandatory though, but this does not include RVO. 除了在 C++17 中保证 RVO 之外,在什么情况下强制复制省略?
  • 恕我直言,如果你有一个std::vector&lt;CObject&gt;,它会是一个更好的例子,因为如果CObjects 的复制成本很高,那么复制与否会产生很大的不同,但在这方面你的两个版本不差别很大
  • @Ivan 那是 NRVO(即命名为 RVO)。确实没有保证 NRVO。
  • @Ivan 在我看来,即使语言已经发生了变化,您也非常坚决不更改您习惯使用的术语。已弃用...如何?

标签: c++ c++11 stl c++14 stdvector


【解决方案1】:

特别是对 C++11 的扩展是否仍然需要?

没有。在最好的情况下,RVO (返回值优化) 将启动,这将完全忽略任何复制/移动。

在最坏的情况下,对象将被移出函数。 std::vector 的移动非常便宜(与仅几个指针交换相比)。

这是因为表达式Filter(some_input)std::vector&lt;CObject*&gt; 类型的右值,而std::vector 的构造函数有一个接受右值引用的重载:@ 987654321@.

【讨论】:

  • 如果我被 C++ 98 编译器卡住了怎么办?
  • @GauravSehgal:说真的,您可以选择依赖 RVO 或使用输出参数。
【解决方案2】:

在过去,我们被训练使用通过引用传递的结果参数,以避免不必要地复制数据。

实际上,即使在使用旧的 C++ 编译器时,这也是非常糟糕的建议:首先为了清晰而编写,其次才是效率。

特别是,通过引用值返回可防止在调用者const 中生成值(这提高了清晰度并且提供了其他优化机会)。

当然,如果分析表明这是一个性能瓶颈,那么就必须进行必要的更改。使用 RVO 和 NRVO(现在很常见),并将移动语义作为备份,现在不太可能成为性能瓶颈。

【讨论】:

  • 当示例是指针向量时尤其如此 - 复制它会很快;所以完全不用担心效率。
【解决方案3】:

当您从函数返回值时,编译器会应用返回值优化以避免复制。 所以,这两种情况都是相似的。 你可以阅读更多there

【讨论】:

  • 编译器是否应用RVO视情况而定。
猜你喜欢
  • 2013-07-07
  • 2019-05-06
  • 2022-01-15
  • 2012-07-17
  • 2011-03-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多