我需要堆栈溢出的意见来解决一直关注循环效率的问题。现在,当我开始编程时,“让它工作”是一个重中之重,我的大多数for循环都是这样的。
for (int i = 0; i < N; i++) {;}
然后我就开始了,特别是在C ++开发中,预增量会为你节省一些电话,并且考虑到这将是N次调用,并且它不会改变我养成习惯的可读性。
for (int i = 0; i < N; ++i) {;}
这已经足够好了一段时间,但专注于可读性,在阅读了Steve McConnell撰写的一些Code Complete之后,我到了这里。
for (int loop_index = 0; loop_index < loop_count; ++loop_index) {;}
这些变量会根据代码的上下文而改变。然后我读了一些关于内置类型构造函数和赋值的Effective C ++。而且基本上就是
之间的区别int i = 42;
和
int i(42);
是前者调用构造函数和赋值运算符,而后者只调用构造函数。所以我在编码的过程中将其纳入了常规。所以我的问题是,这是编写for循环最有效和最易读的方法:
for (int loop_index(0); loop_index < loop_counter; ++loop_index) {;}
答案 0 :(得分:5)
实际上,
for (int i = 0; i < N; i++) {;}
很好。 i
是int
,因此编译器无论如何都会优化后增量。是否使用int
或int i(42);
初始化int i = 42;
也是一个品味问题。
我也会调用迭代器i
,而不是loop_index
。前者无处不在,而后者则很奇怪。
但是,如果您正在处理迭代器,则图片会发生变化。机会it++
仍然会优化到++it
,但在这里,我宁愿使用预增量。
答案 1 :(得分:2)
如果你没有使用迭代器,那应该没关系,因为编译器会将它转换为相同的代码。
附录:如果您正在使用迭代器:
for(vector<int>::iterator i = a.begin(); i != a.end(); ++i)
然后++ i是i.operator ++()而i ++是i.operator ++(int),这可能意味着两件事。
顺便说一句。如果这是一个问题,您可以测量性能。
答案 2 :(得分:2)
首先,你的最后一点是不正确的。这一行
int i = 42;
复制初始化(请参阅此相关GoTW)。那里没有任务。如需作业,您需要
int i;
i = 42;
其次,在处理整数类型等内置函数时,编译器生成的代码可能没有区别。您应该分析不同的选项并查看。
答案 3 :(得分:1)
如果您使用的是内置类型或大多数迭代器,则所有这些都将编译为相同的代码。
所以我坚持用C ++最习惯的那个。
for (int i = 0; i < N; ++i) {;}
或者如果你想要罗嗦(但我和k传统上是循环索引)
for (int loop_index = 0; loop_index < loop_count; ++loop_index) {;}
作为我最初声明的证据:这两段代码生成相同的汇编代码。 (使用g++ -Os -S test.cpp
编译的OS X上的g ++ 4.0.1)
void f(int); // So that smart compilers can't optimise away the loop entirely.
void g()
{
int N=100;
// for( int i=0; i<N; i++)
for (int i(0); i < N; ++i)
{
f(i);
}
}
为完整起见,生成的代码为:
.globl __Z1gv
__Z1gv:
LFB2:
pushl %ebp
LCFI0:
movl %esp, %ebp
LCFI1:
pushl %esi
LCFI2:
xorl %esi, %esi
subl $20, %esp
LCFI3:
L2:
movl %esi, (%esp)
incl %esi
call L__Z1fi$stub
cmpl $100, %esi
jne L2
addl $20, %esp
popl %esi
leave
ret
答案 4 :(得分:0)
虽然其他人已经很好地涵盖了后期与预增量和初始化,但我想补充一点,在大多数情况下使用int i
比int loop_index
更具可读性,因为其他人都是使用和期待。
当你有多个循环,以及循环索引之间复杂的交互时,你可能想要调用它的唯一情况。例如
for (int row = 0; row < rows; row++) {
for (int column = 0; column < columns; column++) {
stuff[row * columns + column] = calc_stuff(row, column);
}
}
答案 5 :(得分:0)
高效?不,它很可能是相同的,因为大多数编译器将优化int和简单指针的后增量和初始化。至于loop_index是否比i,IMO更具可读性,它对简单计数器的可读性较差。
如果它是一个迭代器,那就是不同的故事,编译器不能总是优化重载的后增量或迭代器的双重初始化。我也更喜欢将迭代对象的名称用于迭代器,因为它反映了更好地使用的内容,使用对象的名称在使用箭头时看起来更自然 - &gt;运算符取消引用迭代器。