【问题标题】:Trusting the Return Value Optimization信任返回值优化
【发布时间】:2010-01-25 11:31:38
【问题描述】:

您如何使用返回值优化
在任何情况下,我可以信任现代编译器来使用优化,还是应该始终以安全的方式返回某种类型的指针/使用引用作为参数?

是否存在无法进行返回值优化的已知情况? 在我看来,返回值优化对于编译器来说是相当容易执行的。

【问题讨论】:

  • 请记住,当编译器确定 RVO 在特定情况下实际上不是优化时,它可能会决定执行此操作。因此,您不仅要相信编译器会在有用时执行它,而且您还必须相信它在不合适时执行。
  • 澄清一下:不合适的常见情况是返回的类型可以在寄存器中传递,例如Radians 类。 RVO 技术使用分配在堆栈上的空间,因此具有访问内存的开销。
  • @MSalters 好的,很有趣。基本上,我感兴趣的优化是避免例如 std::vector 被复制。

标签: c++ variable-assignment return-value-optimization


【解决方案1】:

无论何时启用编译器优化(在大多数编译器中,即使优化被禁用),RVO 都会发生。 NRVO 不太常见,但大多数编译器也会执行此优化,至少在启用优化时是这样。

你是对的,优化对于编译器来说相当容易执行,这就是编译器几乎总是这样做的原因。唯一“无法实现”的情况是优化不适用的情况:RVO 仅在您返回未命名的临时文件时适用。如果你想返回一个命名的局部变量,则应用 NRVO,虽然编译器实现起来稍微复杂一些,但它是可行的,现代编译器对此没有任何问题。

【讨论】:

  • 特别是,如果你有 2 个命名变量并在运行时选择一个返回,显然编译器无法执行 NRVO :)
  • Matthieu,我认为两个未命名的出口也是如此? (即“如果 (...) 返回 A() 否则返回 B();”
  • @Viktor:不——那是 RVO,而不是 NRVO。只有其中一个将被建造。所以两个代码路径可以使用相同的内存,也就是为返回值保留的内存。这就是 RVO 的本质:直接在为其保留的内存中创建返回值。
  • Matthieu:不,如果有两个可能返回的变量,NRVO 仍然是可能的。有时我的函数有一个“if”语句。在一个分支中,我构造了一个命名值,对其进行操作并返回它;在另一个分支中,我做同样的事情,但可能使用不同的构造函数。编译器没有理由不能优化它,但我很确定我的不能(Visual C++)。
【解决方案2】:
【解决方案3】:

为了有最好的机会,你可以返回一个直接在 return 语句中构造的对象[谁能记得这个成语的名字 - 我忘记了]:

Foo f() {
    ....
    return Foo( ... );
}

但与所有优化一样,编译器总是可以选择不这样做。归根结底,如果您需要返回一个值,那么您别无选择,只能信任编译器 - 指针和引用不会削减它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-02
    • 2020-06-09
    • 2016-06-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多