省略号代表的代码几乎肯定会使任何实际性能差异降至噪音水平。但是,你对所有假设并不正确。
每次迭代都需要将max加载到处理器寄存器中,然后在i和max之间进行比较
也许是这样,但可能不是。这取决于你的代码,但是任何合理的优化编译器都能检测出计数器是否在迭代之间发生变化。
我不确定你从哪里得到了一些想法,但它们有点误导,并且没有考虑到优化编译器的工作原理。查看你的反汇编并自己看看真正的区别是什么。哦,该死,我来做吧(这很有趣):
程序为:
int main(int argc, char *argv[]){
int max = 10;
for (int i = max-1; i >= 0; i--)
{
cout << i;
}
return 0;
}
生成的汇编代码(VS2010版本,以下注释为本人添加)如下所示:
int main(int argc, char *argv[]){
00341000 push esi
int max = 10
for (int i = max-1
00341001 mov esi,9
00341006 jmp main+10h (341010h)
00341008 lea esp,[esp]
0034100F nop
{
cout << i
00341010 mov ecx,dword ptr [__imp_std::cout (342048h)]
00341016 push esi
00341017 call dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (342044h)]
0034101D dec esi
0034101E jns main+10h (341010h)
}
对于更通俗易懂的版本...
int main(int argc, char *argv[]){
00AC1000 push esi
int max = 10;
for (int i = 0; i < max; i++)
00AC1001 xor esi,esi
{
cout << i;
00AC1003 mov ecx,dword ptr [__imp_std::cout (0AC2048h)]
00AC1009 push esi
00AC100A call dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (0AC2044h)]
00AC1010 inc esi ; increment esi
00AC1011 cmp esi,0Ah ; compare to 10 (0Ah)
00AC1014 jl main+3 (0AC1003h) ; if less, jump to top
}
所以,第一个版本使用了
jns
指令(如果不是有符号数则跳转),因此比较有点简化(与0比较)。它还包含了一些其他指令,但没有比较。然而,请注意,在第二个版本中所做的比较也是静态的。它知道在循环期间
max
不会改变,因此可以相应地优化该部分。但我要强调一下,这不太可能产生可观的性能优势。即使是我Windows电脑上的高性能计时器也无法给出两者之间的明显统计差异,因为对
cout
的调用时间比循环指令长得多。
for (int i = max; i--;)
比for (int i = max-1; i >= 0; i--)
更符合惯用语,因为它适用于无符号索引类型。 - ildjarnmax
。 - Useless