简体   繁体   English

函数调用与局部变量

[英]Function calls vs. local variables

I often see functions where other functions are called multiple times instead of storing the result of the function once. 我经常看到多次调用其他函数的函数,而不是一次存储函数的结果。

ie (1) : (1)

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

Instead I would write it that way, (2) : 相反,我会这样写, (2)

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

I think version 2 is much better to read and better to debug. 我认为版本2更好阅读,更好地调试。 But I'm wondering why people do it like in number 1? 但我想知道为什么人们会像1号那样做? Is there anything I don't see? 有什么我看不到的吗? Performance Issue? 绩效问题? When I look at it, I see in the worst case 4 function calls in number (1) instead of 1 function call in number (2), so performance should be worse in number (1), shouldn't it? 当我看到它时,我在最坏的情况下看到数字(1)中的4个函数调用而不是数字(2)中的1个函数调用,因此性能应该在数字(1)中更差,不是吗?

I'd use (2) if I wanted to emphasize that the same value is used throughout the code, or if I wanted to emphasize that the type of that value is int . 我会使用(2)如果我想强调在整个代码中使用相同的值,或者如果我想强调该值的类型是int Emphasizing things that are true but not obvious can assist readers to understand the code quickly. 强调真实但不明显的东西可以帮助读者快速理解代码。

I'd use (1) if I didn't want to emphasize either of those things, especially if they weren't true, or if the number of times that TestFunction() is called is important due to side-effects. 我会使用(1)如果我不想强调其中任何一个,特别是如果它们不是真的,或者由于副作用而调用TestFunction()的次数很重要。

Obviously if you emphasize something that's currently true, but then in future TestFunction() changes and it becomes false, then you have a bug. 显然,如果你强调一些当前正确的东西,但是在未来的TestFunction()它会发生变化而变得错误,那么你就有了一个bug。 So I'd also want either to have control of TestFunction() myself, or to have some confidence in the author's plans for future compatibility. 所以我也想要自己控制TestFunction() ,或者对作者未来兼容性的计划有信心。 Often that confidence is easy: if TestFunction() returns the number of CPUs then you're happy to take a snapshot of the value, and you're also reasonably happy to store it in an int regardless of what type it actually returns. 通常这种信心很容易:如果TestFunction()返回CPU的数量,那么您很乐意拍摄值的快照,并且您也很乐意将它存储在int而不管它实际返回的是什么类型。 You have to have minimal confidence in future compatibility to use a function at all, eg be confident that it won't in future return the number of keyboards. 您必须对将来使用功能的兼容性信心不足,例如确信它将来不会返回键盘的数量。 But different people sometimes have different ideas what's a "breaking change", especially when the interface isn't documented precisely. 但不同的人有时会有不同的想法,这是一个“突破性变化”,特别是当界面没有准确记录时。 So the repeated calls to TestFunction() might sometimes be a kind of defensive programming. 因此,对TestFunction()的重复调用有时可能是一种防御性编程。

When a temporary is used to store the result of a very simple expression like this one, it can be argued that the temporary introduces unecessary noise that should be eliminated. 当临时用于存储像这样的非常简单的表达式的结果时,可以认为临时引入了应该消除的不必要的噪声。

In his book "Refactoring: Improving the Design of Existing Code" , Martin Fowler lists this elimination of temporaries as a possibly beneficial refactoring ( Inline temp ). 在他的“重构:改进现有代码的设计”一书中 ,Martin Fowler将这种临时消除列为可能有益的重构( Inline temp )。

Whether or not this is a good idea depends on many aspects: 这是否是一个好主意取决于许多方面:

  • Does the temporary provides more information than the original expression, for example through a meaningful name? 临时提供的信息是否比原始表达式更多,例如通过有意义的名称?
  • Is performance important? 性能重要吗? As you noted, the second version without temporary might be more efficient (most compilers should be able to optimize such code so that the function is called only once, assuming it is free of side-effects). 正如您所指出的,没有临时性的第二个版本可能更有效(大多数编译器应该能够优化这样的代码,以便只调用一次函数,假设它没有副作用)。
  • Is the temporary modified later in the function? 是否在函数后期进行了临时修改? (If not, it should probably be const ) (如果没有,它应该是const
  • etc. 等等

In the end, the choice to introduce or remove such temporary is a decision that should be made on a case by case basis. 最后,引入或删除此类临时的选择是应根据具体情况做出的决定。 If it makes the code more readable, leave it. 如果它使代码更具可读性,请保留它。 If it is just noise, remove it. 如果只是噪音,请将其删除。 In your particular example, I would say that the temporary does not add much, but this is hard to tell without knowing the real names used in your actual code, and you may feel otherwise. 在您的特定示例中,我会说临时不会增加太多,但是如果不知道实际代码中使用的真实姓名,这很难说,而您可能会有其他感觉。

I think version 2 is much better to read and better to debug. 我认为版本2更好阅读,更好地调试。

Agreed. 同意。

so performance should be worse in number (1), shouldn't it? 所以性能应该在数量上更差(1),不是吗?

Not necessarily. 不必要。 If TestFunction is small enough, then the compiler may decide to optimize the multiple calls away. 如果TestFunction足够小,那么编译器可能会决定优化多个调用。 In other cases, whether performance matters depends on how often ExampleFunction is called. 在其他情况下,性能是否重要取决于调用ExampleFunction频率。 If not often, then optimize for maintainability. 如果不经常,则优化可维护性。

Also, TestFunction may have side-effects, but in that case, the code or comments should make that clear in some way. 此外, TestFunction可能有副作用,但在这种情况下,代码或注释应该以某种方式清楚。

The two are not equivalent. 这两者并不相同。 Take for example: 举个例子:

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

In a sane world though, this wouldn't be the case, and I agree that the second version is better. 在一个理智的世界中,情况并非如此,我同意第二个版本更好。 :) :)

If the function, for some reason, can't be inlined, the second will even be more efficient. 如果由于某种原因,该功能无法内联,则第二个功能甚至会更高效。

The second option is clearly superior. 第二种选择显然更优越。

You want to emphasize and ensure that you have three times the same value in the if-statement. 您希望强调确保在if语句中具有三倍相同的值。

Performance should not be a bottleneck in this example. 在此示例中,性能不应成为瓶颈。 In conclusion minimizing the chance for errors plus emphasize same values are much more important then a potential small performance gain. 总之,最小化错误的机会加上强调相同的值比潜在的小的性能增益更重要。

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

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