下面的for循环产生相同的结果,尽管一个使用后增量,另一个使用前增量。
代码如下:
for(i=0; i<5; i++) {
printf("%d", i);
}
for(i=0; i<5; ++i) {
printf("%d", i);
}
我得到了两个for循环相同的输出。我遗漏了什么吗?
下面的for循环产生相同的结果,尽管一个使用后增量,另一个使用前增量。
代码如下:
for(i=0; i<5; i++) {
printf("%d", i);
}
for(i=0; i<5; ++i) {
printf("%d", i);
}
我得到了两个for循环相同的输出。我遗漏了什么吗?
当前回答
是的,你会得到完全相同的输出。为什么你认为他们应该给你不同的产出?
在这样的情况下,增量后或增量前很重要:
int j = ++i;
int k = i++;
f(i++);
g(++i);
你可以通过赋值或传递参数来提供一些值。你在for循环中两者都不做。它只会递增。后-和前-在那里没有意义!
其他回答
代码的结果将是相同的。原因是这两个递增操作可以看作是两个不同的函数调用。两个函数都会导致变量的递增,只有它们的返回值不同。在本例中,返回值被丢弃,这意味着输出中没有可区分的差异。
However, under the hood there's a difference: The post-incrementation i++ needs to create a temporary variable to store the original value of i, then performs the incrementation and returns the temporary variable. The pre-incrementation ++i doesn't create a temporary variable. Sure, any decent optimization setting should be able to optimize this away when the object is something simple like an int, but remember that the ++-operators are overloaded in more complicated classes like iterators. Since the two overloaded methods might have different operations (one might want to output "Hey, I'm pre-incremented!" to stdout for example) the compiler can't tell whether the methods are equivalent when the return value isn't used (basically because such a compiler would solve the unsolvable halting problem), it needs to use the more expensive post-incrementation version if you write myiterator++.
你应该进行预增量的三个原因:
你不必考虑变量/对象是否有重载的增量后方法(例如在模板函数中),并区别对待它(或忘记区别对待它)。 一致的代码看起来更好。 当有人问你“为什么要预增量?”时,你就有机会教他们关于停止问题和编译器优化的理论限制。:)
i++和++i都是在每次执行printf("%d", i)之后执行的,所以没有区别。
在以下情况下会有区别:
int main()
{
for(int i(0); i<2; printf("i = post increment in loop %d\n", i++))
{
cout << "inside post incement = " << i << endl;
}
for(int i(0); i<2; printf("i = pre increment in loop %d\n",++i))
{
cout << "inside pre incement = " << i << endl;
}
return 0;
}
结果:
内接缝= 0
I =循环0后的增量
内贴= 1
I =循环1的增量后
第二个for循环:
内部预启动= 0
I =循环1的前增量
内部pre - incement = 1
I =循环2中的前增量
因为在任何一种情况下,增量都是在循环体之后完成的,因此不会影响循环的任何计算。如果编译器是愚蠢的,使用后增量可能会稍微降低效率(因为通常它需要保留一个预值的副本以供以后使用),但我希望在这种情况下优化消除任何差异。
考虑for循环是如何实现的可能会很方便,本质上是转换为一组赋值、测试和分支指令。在伪代码中,预增量看起来像这样:
set i = 0
test: if i >= 5 goto done
call printf,"%d",i
set i = i + 1
goto test
done: nop
后增量至少会有另一个步骤,但它将是微不足道的优化
set i = 0
test: if i >= 5 goto done
call printf,"%d",i
set j = i // store value of i for later increment
set i = j + 1 // oops, we're incrementing right-away
goto test
done: nop
for构造中的第三条语句只被执行,但它的求值被丢弃而不被处理。 当评估值被丢弃时,前后增量相等。 只有当它们的价值被取走时,它们才会有所不同。