理解返回值优化和临时返回 – C ++

请考虑三个function。

std::string get_a_string() { return "hello"; } std::string get_a_string1() { return std::string("hello"); } std::string get_a_string2() { std::string str("hello"); return str; } 
  1. 在所有这三种情况下RVO会被应用吗?
  2. 在上面的代码中返回一个临时值是否可以? 我相信这是可以的,因为我是以价值回报它,而不是返回任何参考。

有什么想法吗?

在第一种情况下,RVO优化将发生。 RVO是旧function,大多数编译器都支持它。 最后一种情况是所谓的NRVO(命名为RVO)。 这是C ++相对较新的特性。 标准允许但不要求实现NRVO(以及RVO),但是一些编译器支持它。

您可以在Scott Meyers的第20项更多有效的C ++中阅读有关RVO的更多信息。 35个改进程序和devise的新方法

这里有一篇关于Visual C ++ 2005中的NRVO的好文章。

首先,按照你所做的价值回报临时工是完全可以的。 它被复制,虽然原来将超出范围副本不会这样做,并可以安全地使用调用者。

其次,所有这三种情况实际上是相同的(因为无论如何你都不能在第三种情况下访问临时的),编译器甚至可能为它们发出相同的代码。 因此它可以在所有三种情况下使用RVO。 这完全依赖于编译器。

所有情况都是正确的。 他们都将构build一个临时的应用返回types的复制构造函数。 必要的话,如果没有复制构造函数,代码将失败。

在大多数编译器下的所有三种情况下RVO都会发生。 唯一的区别是标准不强制的最后一个。 这是因为你有一个命名variables。 但是大多数编译器都足够聪明,可以将RVO应用到它…后面的声明variables被声明,并且应用到的转换越less,RVO被应用到命名variables的可能性就越大。

顺便说一句,返回一个引用当然可能是你可能在其他代码中看到的。 你不能做的是返回一个引用ta本地对象。

 std::string& get_a_string2() { std::string str("hello"); return str; //error! } 

如你所知,会产生编译时错误。 然而,

 std::string& get_a_string2(std::string& str) { // do something to str return str; //OK } 

将工作得很好。 在这种情况下,不涉及施工或复制施工。 简单地说,该函数返回对其参数的引用。

  1. 这取决于你的编译器 – 你指的是什么平台? 最好的方法是编译一个非常小的testing应用程序,并检查您的编译器生成的ASM。

  2. 是的,这是可以的,虽然你从来没有提到你所关心的事情; 速度? 样式? 你可以在本地临时引用一个const引用 – 临时的生命周期将被扩展到引用的生命周期 – 尝试它并亲自体验! (香草萨特在这里 exaplins这个)见例如post的结尾。

国际海事组织,你几乎总是相信你的编译器优化你的代码。 有很less的情况下,你应该需要关心这种事情(非常低的代码是一个这样的地方,你与硬件寄存器交互)。

 int foo() { return 42; } int main(int, char**) { const int &iRef = foo(); // iRef is valid at this point too! }