【问题标题】:Does return-by-value mean extra copies and extra overhead? C++ [duplicate]按值返回是否意味着额外的副本和额外的开销? C++ [重复]
【发布时间】:2014-04-21 11:00:28
【问题描述】:

考虑以下几点:

class Foo { ... };

Foo rbv();

void caller()
{
  Foo x = rbv(); ← the return-value of rbv() goes into x
  ...
}

Foo rbv()
{
  ...
  return Foo(42, 73); ← suppose Foo has a ctor Foo::Foo(int a, int b)
}

将构造多少个 Foo 类型的对象?

【问题讨论】:

  • Foo的构造函数中添加一条日志消息并找出:)

标签: c++ constructor return-by-value


【解决方案1】:

也许吧。

在 C++11 中,如果值具有移动构造函数,则通过移动而不是复制返回值。这比复制要高效得多。

在某些情况下 - 例如返回局部变量或临时变量(如您在此处所做的那样) - 移动或复制可以被省略。该值直接创建到调用者的堆栈帧中,因此不需要在返回时移动或复制它。喜欢首字母缩略词的人有时称这为 (N)RVO - (Named) Return Value Optimisation。

同样,从临时返回值到x的复制或移动也可以省略。

任何体面的编译器都会实现这个优化,所以你的代码应该只创建一个Foo。您可以通过使析构函数打印一条消息来验证这一点,并观察它只执行一次:http://ideone.com/xydJqY。如果禁用优化,则最多可能有三个对象。

【讨论】:

    【解决方案2】:

    最多可以有两个副本:一个从临时的Foo(42, 73) 到函数的返回值,另一个从函数的返回值到x。但是,这两个副本都符合复制省略的条件,这允许不进行复制而是直接在目标中构造对象,相当于Foo x(42, 73);

    您可以控制编译器利用复制省略的程度;例如,在 GCC 中,您可以使用 -fno-elide-constructors 获取所有两个副本。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-09
      • 1970-01-01
      • 2010-12-05
      • 2018-07-25
      • 1970-01-01
      • 2011-10-10
      相关资源
      最近更新 更多