我经常看到多次调用其他函数的函数,而不是一次存储函数的结果。
即(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)的性能应该更差,不应该吗?
答案 0 :(得分:3)
如果我想强调在整个代码中使用相同的值,或者我想强调该值的类型是int
,我会使用(2)。强调真实但不明显的事情可以帮助读者快速理解代码。
我会使用(1)如果我不想强调其中任何一个,特别是如果它们不是真的,或者TestFunction()
被称为重要的次数是重要的效果 - 。
显然,如果你强调某些目前是真的,但是在未来的TestFunction()
更改中它会变为假,那么你就有了一个错误。所以我也希望自己能够控制TestFunction()
,或者对作者未来兼容性的计划有信心。通常这种信心很容易:如果TestFunction()
返回CPU的数量,那么您很乐意拍摄该值的快照,并且您也很乐意将其存储在int
中,而不管是什么键入它实际返回。您必须对将来使用函数的兼容性信心不足,例如:相信它将来不会返回键盘的数量。但不同的人有时会有不同的想法,这是一个“突破性变化”,特别是当界面没有准确记录时。因此,对TestFunction()
的重复调用有时可能是一种防御性编程。
答案 1 :(得分:2)
当临时用于存储像这样的非常简单的表达式的结果时,可以认为临时引入了应该消除的不必要的噪声。
在他的书"Refactoring: Improving the Design of Existing Code"中,马丁福勒将这种临时消除列为可能有益的重构(Inline temp
)。
这是否是一个好主意取决于很多方面:
const
)最后,选择引入或删除此类临时是一个应根据具体情况做出的决定。如果它使代码更具可读性,请保留它。如果只是噪音,请将其删除。在您的特定示例中,我会说临时不会增加太多,但是如果不知道实际代码中使用的真实姓名,这很难说,而您可能会有其他感觉。
答案 2 :(得分:1)
我认为版本2更好阅读,更好地调试。
同意。
因此,数字(1)的表现应该更差,不应该吗?
不一定。如果TestFunction
足够小,则编译器可能决定优化多个调用。在其他情况下,性能是否重要取决于调用ExampleFunction
的频率。如果不经常,那么优化可维护性。
此外,TestFunction
可能有副作用,但在这种情况下,代码或评论应该以某种方式明确。
答案 3 :(得分:1)
这两者并不相同。举个例子:
int TestFunction()
{
static int x;
return x++;
}
在 sane 世界中,情况并非如此,我同意第二个版本更好。 :)
如果函数由于某种原因无法内联,那么第二个函数甚至会更有效。
答案 4 :(得分:0)
第二个选项显然更好。
您要强调,并确保在if语句中具有相同值的三倍。
在此示例中,性能不应成为瓶颈。总之,与潜在的小幅度性能提升相比,最小化错误机会并强调相同的值更为重要。