中间变量和直接返回函数调用之间是否存在差异?

时间:2014-01-29 20:01:36

标签: c++ runtime

在返回函数中调用函数并调用函数然后在运行时返回值之间是否有任何区别,如下所示:

我的函数原型:

int aFunc(int...);
int bFunc(int...);

我的第一个bFunc返回行:

int bFunc(int...)
{
  ...
  return (aFunc(x,...));
}

我的第二个bFunc返回行:

int bFunc(int...)
{
  ...
  int retVal = aFunc(x,...);
  return retVal;
}

4 个答案:

答案 0 :(得分:4)

回答您的具体问题:

之间不应存在可观察到的差异
return expression;

x = expression;
return x;

当然提供x的类型正确。

但是,在C ++中,

之间可能存在差异
return complicated_expression;

x = some_subexpression;
y = some_other_subexpression;
return complicated_expression_rewritten_in_terms_of_x_and_y;

原因是:C ++保证在评估子表达式期间创建的临时值的析构函数在语句的末尾运行。在some_expression语句结束时计算some_other_subexpression之后,此重构会移动与 return相关联的任何临时值析构函数的副作用 - 之前 - 在x的分配结束时。

我已经看到了真实的生产代码,其中这个重构在程序中引入了一个错误:some_other_subexpression的计算依赖于它在评估{期间“生成的临时值的析构函数的副作用时的正确性{1}}之后运行。重写的代码更容易阅读,但不幸的是也错了。

答案 1 :(得分:2)

如果返回类型更复杂,如std::vector,则可能会有所不同,具体取决于编译器中实现的优化。

返回未命名的向量需要(匿名)返回值优化以避免副本,这是一种常见的优化。返回指定值需要 命名 返回值优化,而not all compilers did in the past

  

Visual C ++ 8.0编译器...添加了一项新功能:命名返回值优化(NRVO)。 NRVO消除了基于堆栈的返回值的复制构造函数和析构函数。这样可以优化冗余复制构造函数和析构函数调用,从而提高整体性能。

答案 2 :(得分:1)

一个好的编译器应该使两者相同(至少在启用优化时)。

理论上,bFunc中有两个复制操作:

  1. 进入堆栈上的局部变量。

  2. 从局部变量进入堆栈的“底部”(bFunc透视图的底部)。

  3. 如果retVal是按值而不是按引用返回的对象(类或结构)(如上例所示),则附加复制操作可能会产生与{{}的大小成比例的开销。 1}}。

    除此之外,复制构造函数应该被调用两次(处理对象时)可能会阻止编译器首先应用优化。

答案 3 :(得分:0)

通常我不会指望任何真正的区别,因为编译器可能会优化临时变量。