之间是否存在差异:
for (int i = 0; i < n; i++)
和:
for (int i(0); i != n; ++i)
他们似乎与我几乎完全相同。哪一个比另一个好?
答案 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
)的倍数。
尽管有相反的说法,但两者之间没有区别
n
和i++
与任何现代编译器和任何合理的编译器
迭代器。因为有些作者声称可能++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
的引用。
总之:在所有三种情况下,第二种变体原则上对执行处理器的工作量较少。