哪个for循环更好/更快?

时间:2014-10-23 07:01:54

标签: c++

之间是否存在差异:

for (int i = 0; i < n; i++)

和:

for (int i(0); i != n; ++i)

他们似乎与我几乎完全相同。哪一个比另一个好?

4 个答案:

答案 0 :(得分:2)

如果n为否定,则第二个会失败; i < n是一种更安全的终止条件。

除此之外,像int这样的简单类型没有区别。

对于更复杂的类型,人们可能更喜欢直接初始化和第二次的预增量。第一个,至少在原则上,可能需要在初始化和每个增量期间进行复制,尽管在许多情况下可以对这些进行优化。

答案 1 :(得分:1)

几乎没有区别。我用g ++编译了一个演示软件。 这是for(int i = 0; i < n; i++)的汇编:

main:
.LFB0:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movl    $10, -4(%rbp)
    movl    $0, -8(%rbp)
    jmp .L2
.L3:
    addl    $1, -8(%rbp)
.L2:
    movl    -8(%rbp), %eax
    cmpl    -4(%rbp), %eax
    jl  .L3    ;------ if compiled with other for loop there is "jne   .L3"
    movl    $0, %eax
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE0:
    .size   main, .-main
    .ident  "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2"
    .section    .note.GNU-stack,"",@progbits

如果用for(int i(0); i != n; ++i)编译它,我评论了不同的行。正如你所看到的,唯一的区别是,在一种情况下,如果较少则比较操作是跳跃,而在另一种情况下,如果不相等则跳转。

答案 2 :(得分:1)

谈论速度是没有意义的,因为这两者都有 不同的东西。但一般情况下:

  • 由于历史原因,所有我见过的代码都使用了副本 for-init-statment 中的初始化(到了 我不确定第二个是否合法。在实践中, 除非你有一个非常非常糟糕的编译器,并且可怕 复杂的迭代器,它不应该有所作为。只是用 这是当地编码标准所说的,并且不用担心 它

  • 从历史上看,i < n一直是首选 即使你碰巧在循环中增加i,它也能正常工作 好。但是,在C ++中,i != n已成为惯用语 它也适用于迭代器和指针。它也一直都是 争辩说,如果你不小心增加索引或 迭代器曾经在循环中过多,最好进入 没有土地比计划似乎工作。无论如何,在 现代C ++,我推荐i != n,除非你的本地编码 标准明确说明, 算法 故意预计i可能超出n(例如,您) 使用步幅,增量为{​​{1}},其中 i += step并不保证是step)的倍数。

  • 尽管有相反的说法,但两者之间没有区别 ni++与任何现代编译器和任何合理的编译器 迭代器。因为有些作者声称可能++i 然而,它更快,它在C ++中变得很平常。如果你有 代码使用++i,或者本地编码标准说使用它, 使用i++;否则,使用i++,只是为了避免参数 那些读得更快的人。 (作者声称 它从未真正发布过基准测试支持 他们的主张。)

结果是:

++i

可能是C ++代码中最惯用的,但在所有情况下, 您应该遵循本地编码标准和现有代码 (如果在遗留项目上工作)。并且不用担心 每个人的相对速度;它几乎肯定不会成功 差异。

答案 3 :(得分:0)

其他人已经说过,在实践中,它没有任何区别。我同意这一点,因为现代编译器只是简化了差异。

如果你在谈论原则,那就有区别(确切地说是三个)。让我们假设前置条件确保两个变体具有相同的效果。

1:int i = 0要求编译器创建一个变量,对其进行初始化,然后将其设置为0(使用其operator =)。在理论平台和编译器上,初始化可能包括将i设置为某个定义的值。另一方面,int i(0)告诉编译器将变量初始化为0,从而可能保存多余的初始化。

2:这部分缺乏精确的知识,有点模糊。对于许多CPU,i < n要求编译器生成减法,提取符号位,然后有条件地跳转。另一方面,i != n需要减法,然后跳过“零”。位。

3:i++要求编译器复制i(返回后再使用),然后递增它。另一方面,++i递增,然后返回对i的引用。

总之:在所有三种情况下,第二种变体原则上对执行处理器的工作量较少。