繁体   English   中英

函数调用与局部变量

[英]Function calls vs. local variables

我经常看到多次调用其他函数的函数,而不是一次存储函数的结果。

(1)

void ExampleFunction()
{ 
    if (TestFunction() > x || TestFunction() < y || TestFunction() == z)
    {
        a = TestFunction();
        return; 
    }
    b = TestFunction();
}

相反,我会这样写, (2)

void ExampleFunction()
{
    int test = TestFunction();
    if (test > x || test < y || test == z)
    {
        a = test;
        return;
    }
    b = test;
}

我认为版本2更好阅读,更好地调试。 但我想知道为什么人们会像1号那样做? 有什么我看不到的吗? 绩效问题? 当我看到它时,我在最坏的情况下看到数字(1)中的4个函数调用而不是数字(2)中的1个函数调用,因此性能应该在数字(1)中更差,不是吗?

我会使用(2)如果我想强调在整个代码中使用相同的值,或者如果我想强调该值的类型是int 强调真实但不明显的东西可以帮助读者快速理解代码。

我会使用(1)如果我不想强调其中任何一个,特别是如果它们不是真的,或者由于副作用而调用TestFunction()的次数很重要。

显然,如果你强调一些当前正确的东西,但是在未来的TestFunction()它会发生变化而变得错误,那么你就有了一个bug。 所以我也想要自己控制TestFunction() ,或者对作者未来兼容性的计划有信心。 通常这种信心很容易:如果TestFunction()返回CPU的数量,那么您很乐意拍摄值的快照,并且您也很乐意将它存储在int而不管它实际返回的是什么类型。 您必须对将来使用功能的兼容性信心不足,例如确信它将来不会返回键盘的数量。 但不同的人有时会有不同的想法,这是一个“突破性变化”,特别是当界面没有准确记录时。 因此,对TestFunction()的重复调用有时可能是一种防御性编程。

当临时用于存储像这样的非常简单的表达式的结果时,可以认为临时引入了应该消除的不必要的噪声。

在他的“重构:改进现有代码的设计”一书中 ,Martin Fowler将这种临时消除列为可能有益的重构( Inline temp )。

这是否是一个好主意取决于许多方面:

  • 临时提供的信息是否比原始表达式更多,例如通过有意义的名称?
  • 性能重要吗? 正如您所指出的,没有临时性的第二个版本可能更有效(大多数编译器应该能够优化这样的代码,以便只调用一次函数,假设它没有副作用)。
  • 是否在函数后期进行了临时修改? (如果没有,它应该是const
  • 等等

最后,引入或删除此类临时的选择是应根据具体情况做出的决定。 如果它使代码更具可读性,请保留它。 如果只是噪音,请将其删除。 在您的特定示例中,我会说临时不会增加太多,但是如果不知道实际代码中使用的真实姓名,这很难说,而您可能会有其他感觉。

我认为版本2更好阅读,更好地调试。

同意。

所以性能应该在数量上更差(1),不是吗?

不必要。 如果TestFunction足够小,那么编译器可能会决定优化多个调用。 在其他情况下,性能是否重要取决于调用ExampleFunction频率。 如果不经常,则优化可维护性。

此外, TestFunction可能有副作用,但在这种情况下,代码或注释应该以某种方式清楚。

这两者并不相同。 举个例子:

int TestFunction()
{
   static int x;
   return x++;
}

在一个理智的世界中,情况并非如此,我同意第二个版本更好。 :)

如果由于某种原因,该功能无法内联,则第二个功能甚至会更高效。

第二种选择显然更优越。

您希望强调确保在if语句中具有三倍相同的值。

在此示例中,性能不应成为瓶颈。 总之,最小化错误的机会加上强调相同的值比潜在的小的性能增益更重要。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM