我在VC++中有以下代码:
for (int i = (a - 1) * b; i < a * b && i < someObject->someFunction(); i++)
{
// ...
}
字符串
据我所知,编译器优化了所有这些算术运算,它们不会在每个循环中执行,但我不确定他们是否能告诉上面的函数每次也返回相同的值,并且不需要每次都调用它。
将所有计算保存到变量中是更好的做法,还是仅仅依靠编译器优化来获得更可读的代码?
int start = (a - 1) * b;
int expra = a * b;
int exprb = someObject->someFunction();
for (int i = startl i < expra && i < exprb; i++)
{
// ...
}
型
6条答案
按热度按时间ss2ws0br1#
简短的回答:如果编译器可以推断出每次运行
someObject->someFunction()
和缓存一次结果都会产生相同的效果,则允许(但不保证)这样做。这种静态分析是否可能取决于你的程序:具体地说,someObject
的静态类型是什么,它的动态类型预期是什么,以及someFunction()
实际上做什么,无论是virtual
等等。一般来说,如果它只需要做一次,那么就用一种只可以做一次的方式来写你的代码,这样就不必担心编译器会做什么:
字符串
或者,如果你喜欢简洁:
型
hgncfbus2#
根据我的经验,VC++编译器不会优化函数调用,除非它能在编译调用代码时看到函数的实现,所以把调用移到循环外是个好主意。
atmip9wb3#
如果一个函数和它的调用者位于同一个编译单元中,编译器通常可以推断出关于它的 * 一些 * 事实-例如,它的输出可能不会在后续调用中改变。然而,通常情况下,情况并非如此。
在你的例子中,为这些简单的算术表达式赋值变量并没有真正改变生成的目标代码,在我看来,这会使代码变得不那么可读。除非你有一堆长表达式,不能合理地放在一两行内,否则你应该避免使用临时变量--如果没有其他原因,那么只是为了减少命名空间污染。
使用临时变量意味着程序员需要大量的管理开销,以保持它们的独立性并避免意外的副作用。它也使得代码片段的重用变得更加困难。
另一方面,将函数的结果赋给变量可以帮助编译器通过显式避免多个函数调用来更好地优化代码。
就我个人而言,我会这样做:
字符串
7gyucuyw4#
编译器不能对你的函数是否每次都返回相同的值做出任何假设。让我们假设你的对象是一个套接字,编译器怎么可能知道它的输出是什么?
此外,编译器在这种循环中所能进行的优化很大程度上取决于a和B是否声明为
const
,以及它们是否是局部的。使用高级优化方案,它可能能够推断出a和B既没有在循环中修改,也没有在函数中修改(同样,你可能会想象你的对象持有对它们的引用)。好吧,简而言之:使用你的代码的第二版本!
nbysray55#
编译器很可能每次都调用该函数。
如果你关心代码的可读性,那么使用:
字符串
IMHO,长行并不能提高可读性。
编写简短的行并执行多个步骤来获得结果,不会影响性能,这正是我们使用编译器的原因。
gg0vcinb6#
实际上,你可能会问编译器是否会内联函数someFunction(),以及它是否会看到someObject在每个循环中是同一个示例,如果它都这样做,它可能会“缓存”返回值,而不是不断重新评估它。
这在很大程度上可能取决于你使用什么优化设置,在VC以及任何其他编译器中,尽管我不确定VC是否像gnu一样给你提供了那么多的标志。
我经常觉得程序员依赖编译器来优化他们自己可以轻松优化的东西是不可思议的。如果你知道它每次都会得到相同的结果,只要将表达式移到for循环的第一部分即可:
只需这样做,不要依赖编译器:
字符串