在我的设计与分析讲座中 算法讲师表示,对于以下示例算法,for 循环将比 while 循环花费更少的时间。
1. for(int i=0;i<5;i++)
{
2. print(i);
}
1. int i=0;
2. while(i<5)
{
3. print(i);
4. i++;
}
他说编译器会读取 for while 的 1. 5 次第 2. 4 行因此总共时间 5+4=9 但在 while 循环的情况下。编译器将读取 1. 1 次,2. 5 次,3 次,4 次,4. 4 次。因此总时间 1+5+4+4 = 14time 请告诉我这是对的吗? for循环比while循环快吗?
谢谢。
至少对于 MSVC 16 (VS 2010),这两种情况下的代码几乎相同:
为了
; Line 5
xor esi, esi
$LL3@main:
; Line 6
push esi
push OFFSET ??_C@_03PMGGPEJJ@?$CFd?6?$AA@
call _printf
inc esi
add esp, 8
cmp esi, 5
jl SHORT $LL3@main
同时
; Line 4
xor esi, esi
$LL2@main:
; Line 6
push esi
push OFFSET ??_C@_03PMGGPEJJ@?$CFd?6?$AA@
call _printf
; Line 7
inc esi
add esp, 8
cmp esi, 5
jl SHORT $LL2@main
在所有现代编译器中循环分析是在较低级别的中间表示上完成的(即,当所有高级循环结构都扩展为标签和跳转时)。对于编译器来说,两个循环绝对等效。
我将传递性能(提示:没有区别,请检查生成的 IR 或程序集以进行证明),但是语法和维护有两个重要的区别。
语法
i
变量的范围不同。在 for
情况下,i
只能在 for
header 和 body 中访问,而在 while
情况下,它在循环之后可用。作为一般规则,最好有更严格的范围,更少的变量in-flight意味着编码时需要担心的上下文更少。
维护
for
循环具有将所有迭代操作紧密分组在一起的巧妙优势,因此可以一次性检查并检查它们。
此外,在引入
continue
语句时有一个重要的区别:
for(int i = 0; i != 10; ++i) {
if (array[i] == nullptr) { continue; }
// act on it
}
int i = 0;
while (i != 10) {
if (array[i] == nullptr) { continue; }
// act on it
++i;
}
在
while
的情况下,continue
的引入产生了一个错误:无限循环,因为不再实现计数器。
影响
for
循环对于常规迭代模式来说更具可读性和全面性。更好的是,C++11 中的 range-for 语句:
for (Item const& item : collection) {
}
其中迭代完全由编译器处理,所以你一定不会搞砸! (这使得
for_each
算法有点没有实际意义......我们希望旧的形式开始撤退)
推论:
while
循环应保留给不规则的迭代模式,这样它们将在代码审查期间吸引特别注意,并通过突出案例的不规则性来吸引未来的维护者。