C++ “for”循环中的后增量和预增量产生相同的输出
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4706199/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Post-increment and pre-increment within a 'for' loop produce same output
提问by theReverseFlick
The following for loops produce identical results even though one uses post increment and the other pre-increment.
即使一个使用后增量和另一个预增量,以下 for 循环也会产生相同的结果。
Here is the code:
这是代码:
for(i=0; i<5; i++) {
printf("%d", i);
}
for(i=0; i<5; ++i) {
printf("%d", i);
}
I get the same output for both 'for' loops. Am I missing something?
对于两个“for”循环,我得到相同的输出。我错过了什么吗?
回答by danben
After evaluating i++
or ++i
, the new value of i
will be the same in both cases. The difference between pre- and post-increment is in the result of evaluating the expression itself.
评估i++
or 后++i
, 的新值i
在两种情况下都相同。前增量和后增量之间的区别在于评估表达式本身的结果。
++i
increments i
and evaluates to the new value of i
.
++i
递增i
并计算为 的新值i
。
i++
evaluates to the old value of i
, and increments i
.
i++
计算为 的旧值i
,并递增i
。
The reason this doesn't matter in a for loop is that the flow of control works roughly like this:
这在 for 循环中无关紧要的原因是控制流的工作方式大致如下:
- test the condition
- if it is false, terminate
- if it is true, execute the body
- execute the incrementation step
- 测试条件
- 如果为假,则终止
- 如果为真,则执行主体
- 执行增量步骤
Because (1) and (4) are decoupled, either pre- or post-increment can be used.
因为 (1) 和 (4) 是解耦的,所以可以使用前置或后置增量。
回答by jason
Well, this is simple. The above for
loops are semantically equivalent to
嗯,这很简单。上面的for
循环在语义上等同于
int i = 0;
while(i < 5) {
printf("%d", i);
i++;
}
and
和
int i = 0;
while(i < 5) {
printf("%d", i);
++i;
}
Note that the lines i++;
and ++i;
have the same semantics FROM THE PERSPECTIVE OF THIS BLOCK OF CODE. They both have the same effect on the value of i
(increment it by one) and therefore have the same effect on the behavior of these loops.
请注意,从代码块的角度来看,行i++;
和++i;
具有相同的语义。它们都对i
(将其增加 1)的值具有相同的影响,因此对这些循环的行为具有相同的影响。
Note that there would be a difference if the loop was rewritten as
请注意,如果将循环重写为
int i = 0;
int j = i;
while(j < 5) {
printf("%d", i);
j = ++i;
}
int i = 0;
int j = i;
while(j < 5) {
printf("%d", i);
j = i++;
}
This is because in first block of code j
sees the value of i
after the increment (i
is incremented first, or pre-incremented, hence the name) and in the second block of code j
sees the value of i
before the increment.
这是因为在第一个代码块中j
看到i
增量之后的值(i
首先增加,或预先增加,因此得名),而在第二个代码块中j
看到i
增量之前的值。
回答by Anders Sj?qvist
The result of your code will be the same. The reason is that the two incrementation operations can be seen as two distinct function calls. Both functions cause an incrementation of the variable, and only their return values are different. In this case, the return value is just thrown away, which means that there's no distinguishable difference in the output.
您的代码的结果将是相同的。原因是这两个递增操作可以看作是两个不同的函数调用。这两个函数都会引起变量的递增,只是它们的返回值不同。在这种情况下,返回值只是被丢弃了,这意味着输出中没有可区分的差异。
However, under the hoodthere's a difference: The post-incrementation i++
needs to create a temporary variableto 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
,然后执行增量并返回临时变量。预增量++i
不会创建临时变量。当然,当对象很简单时,任何体面的优化设置都应该能够将其优化掉int
,但请记住 ++ 运算符在更复杂的类(如迭代器)中被重载。由于这两个重载方法可能有不同的操作(例如,一个可能想要输出“嘿,我是预先递增的!”到标准输出),编译器无法在不使用返回值时判断这些方法是否等效(主要是因为这样的编译器会解决无法解决的停机问题),如果您编写myiterator++
.
Three reasons why you should pre-increment:
您应该预先递增的三个原因:
- You won't have to think about whether the variable/object might have an overloaded post-incrementation method (for example in a template function) and treat it differently (or forget to treat it differently).
- Consistent code looks better.
- When someone asks you "Why do you pre-increment?" you'll get the chance to teach them about the halting problem and theoretical limits of compiler optimization. :)
回答by Adam Liss
This is one of my favorite interview questions. I'll explain the answer first, and then tell you why I like the question.
这是我最喜欢的面试问题之一。我会先解释答案,然后告诉你为什么我喜欢这个问题。
Solution:
解决方案:
The answer is that both snippets print the numbers from 0 to 4, inclusive. This is because a for()
loop is generally equivalent to a while()
loop:
答案是两个片段都打印了从 0 到 4(包括 0 到 4)的数字。这是因为for()
循环通常等同于while()
循环:
for (INITIALIZER; CONDITION; OPERATION) {
do_stuff();
}
Can be written:
可以写成:
INITIALIZER;
while(CONDITION) {
do_stuff();
OPERATION;
}
You can see that the OPERATION is alwaysdone at the bottom of the loop. In this form, it should be clear that i++
and ++i
will have the same effect: they'll both increment i
and ignore the result. The new value of i
is not tested until the next iteration begins, at the top of the loop.
您可以看到 OPERATION始终在循环的底部完成。在这种形式中,应该很清楚i++
和++i
将具有相同的效果:它们都会增加i
并忽略结果。的新值i
直到下一次迭代开始,在循环的顶部才被测试。
Edit: Thanks to Jason for pointing out that this for()
to while()
equivalence does nothold if the loop contains control statements (such as continue
) that would prevent OPERATION
from being executed in a while()
loop. OPERATION
is alwaysexecuted just before the next iteration of a for()
loop.
编辑:感谢贾森指出,这for()
对while()
等价并没有如果循环包含控制语句(如持有continue
),这将防止OPERATION
从一个执行while()
循环。 OPERATION
是永远只是一个下一次迭代之前执行for()
循环。
Why it's a Good Interview Question
为什么这是一个很好的面试问题
First of all, it takes only a minute or two if a candidate tells the the correct answer immediately, so we can move right on to the next question.
首先,如果候选人立即说出正确答案,只需一两分钟,这样我们就可以直接进入下一个问题。
But surprisingly (to me), many candidates tell me the loop with the post-increment will print the numbers from 0 to 4, and the pre-increment loop will print 0 to 5, or 1 to 5. They usually explain the difference between pre- and post-incrementing correctly, but they misunderstand the mechanics of the for()
loop.
但令人惊讶的是(对我而言),许多候选人告诉我,带有后增量的循环将打印从 0 到 4 的数字,而前增量循环将打印 0 到 5,或 1 到 5。他们通常会解释两者之间的区别前后递增正确,但他们误解了for()
循环的机制。
In that case, I ask them to rewrite the loop using while()
, and this really gives me a good idea of their thought processes. And that's why I ask the question in the first place: I want to know how they approach a problem, and how they proceed when I cast doubt on the way their world works.
在这种情况下,我要求他们使用 重写循环while()
,这确实让我对他们的思维过程有了很好的了解。这就是我首先提出这个问题的原因:我想知道他们如何解决问题,以及当我对他们的世界运作方式产生怀疑时他们如何进行。
At this point, most candidates realize their error and find the correct answer. But I had one who insisted his original answer was right, then changed the way he translated the for()
to the while()
. It made for a fascinating interview, but we didn't make an offer!
在这一点上,大多数考生意识到自己的错误并找到了正确的答案。但我有一个谁坚持他原来的答案是正确的,那么改变他翻译的方式for()
到while()
。这是一次引人入胜的采访,但我们没有提供报价!
Hope that helps!
希望有帮助!
回答by tvanfosson
Because in either case the increment is done after the body of the loop and thus doesn't affect any of the calculations of the loop. If the compiler is stupid, it might be slightly less efficient to use post-increment (because normally it needs to keep a copy of the prevalue for later use), but I would expect any differences to be optimized away in this case.
因为在任何一种情况下,增量都是在循环体之后完成的,因此不会影响循环的任何计算。如果编译器很笨,那么使用后增量的效率可能会稍低一些(因为通常它需要保留pre值的副本以备后用),但我希望在这种情况下可以优化任何差异。
It might be handy to think of how the for loop is implemented, essentially translated into a set of assignments, tests, and branch instructions. In pseudo-code the pre-increment would look like:
考虑一下 for 循环是如何实现的,本质上是转换为一组赋值、测试和分支指令可能会很方便。在伪代码中,预增量看起来像:
set i = 0
test: if i >= 5 goto done
call printf,"%d",i
set i = i + 1
goto test
done: nop
Post-increment would have at least another step, but it would be trivial to optimize away
后增量至少还有一个步骤,但是优化掉是微不足道的
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
回答by iss42
If you wrote it like this then it would matter :
如果你这样写,那就很重要了:
for(i=0; i<5; i=j++) {
printf("%d",i);
}
Would iterate once more than if written like this :
比这样写会迭代一次:
for(i=0; i<5; i=++j) {
printf("%d",i);
}
回答by Yola
You could read Google answer for it here: http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Preincrement_and_Predecrement
您可以在此处阅读 Google 的答案:http: //google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Preincrement_and_Predecrement
So, main point is, what no difference for simple object, but for iterators and other template objects you should use preincrement.
所以,重点是,简单对象没有什么区别,但是对于迭代器和其他模板对象,您应该使用预增量。
EDITED:
编辑:
There are no difference because you use simple type, so no side effects, and post- or preincrements executed after loop body, so no impact on value in loop body.
没有区别,因为你使用的是简单类型,所以没有副作用,并且在循环体之后执行后或预增量,所以对循环体中的值没有影响。
You could check it with such a loop:
你可以用这样的循环检查它:
for (int i = 0; i < 5; cout << "we still not incremented here: " << i << endl, i++)
{
cout << "inside loop body: " << i << endl;
}
回答by Petruza
The third statement in the for construct is only executed, but its evaluated value is discarded and not taken care of.
When the evaluated value is discarded, pre and post increment are equal.
They only differ if their value is taken.
for 结构中的第三条语句只被执行,但它的评估值被丢弃而不被处理。
当评估值被丢弃时,前后增量相等。
只有当它们的值被采用时它们才会不同。
回答by Hoàng Long
Both i++ and ++i is executed after printf("%d", i) is executed at each time, so there's no difference.
i++ 和 ++i 都是在每次执行 printf("%d", i) 之后执行的,所以没有区别。
回答by Nawaz
Yes, you'll get exactly same outputs for both. why do you think they should give you different outputs?
是的,您将获得完全相同的输出。为什么你认为他们应该给你不同的输出?
Post-increment or pre-increment matters in situations like this:
在这样的情况下,后增量或前增量很重要:
int j = ++i;
int k = i++;
f(i++);
g(++i);
where you provide some value, either by assigning or by passing an argument. You do neither in your for
loops. It gets incremented only. Post- and pre- don't make sense there!
您可以通过分配或传递参数来提供一些值。你在你的for
循环中都不做。它只会增加。后和前在那里没有意义!