返回中间变量和直接返回函数调用有区别吗?

问题描述 投票:0回答:4

return
中调用函数与调用函数然后在运行时
return
计算值之间有什么区别,如下所示:

我的函数原型:

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

我的第一个 bFunc 返回行:

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

我的第二个 bFunc 返回行:

int bFunc(int...)
{
  ...
  int retVal = aFunc(x,...);
  return retVal;
}
c++ runtime
4个回答
6
投票

回答您的具体问题:之间不应该有明显的差异

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
语句末尾)移动到
before
它(在赋值结束时)到x

我见过现实世界的生产代码,其中这种重构在程序中引入了一个错误:

some_other_subexpression

的计算的正确性取决于随后运行的

some_subexpression
评估期间生成的临时值的析构函数的副作用。重写后的代码更容易阅读,但不幸的是也是错误的。
    


2
投票
std::vector

这样更复杂的类型,则可能会有所不同,具体取决于编译器中实现的优化。


返回未命名向量需要(匿名)

返回值优化

以避免复制,这是一种常见的优化。虽然返回命名值需要 named 返回值优化,但 过去并非所有编译器都这样做:

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


1
投票

理论上,

bFunc

中有两次复制操作:


    进入堆栈上的局部变量。
  1. 从局部变量开始,进入栈的“底部”(
  2. bFunc

    视角下的底部)。

    
    

  3. 如果
retVal

是按值而不是按引用返回的对象(类或结构)(如上面的情况),则额外的复制操作可能会产生与

retVal
的大小成比例的开销。

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


0
投票

© www.soinside.com 2019 - 2024. All rights reserved.