为什么在 for 循环的迭代部分将前置增量更改为后置增量不会产生影响?
为什么
int x = 2;
for (int y =2; y>0;y--){
System.out.println(x + " "+ y + " ");
x++;
}
打印出来的结果和这个一样?
int x = 2;
for (int y =2; y>0;--y){
System.out.println(x + " "+ y + " ");
x++;
}
到目前为止,据我了解,后递增首先“按原样”使用,然后递增。都是先加后用预增量。为什么这不适用于 for 循环体?
Why does this
int x = 2;
for (int y =2; y>0;y--){
System.out.println(x + " "+ y + " ");
x++;
}
prints the same as this?
int x = 2;
for (int y =2; y>0;--y){
System.out.println(x + " "+ y + " ");
x++;
}
As far, as I understand a post-increment is first used "as it is" then incremented. Are pre-increment is first added and then used. Why this doesn't apply to the body of a for loop?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(27)
后增量和预增量运算符之间存在相当大的混淆,这可以从“算法,第四版 Robert Sedgewick 和 Kevin Wayne”的摘录中轻松理解
例如
There is quite confusion in between post and pre increment operator, this can be easily understand from this excerpt of "Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne"
for example
该循环相当于:
正如您从阅读该代码中看到的那样,在 for 循环的第三部分中使用后递减运算符还是前递减运算符并不重要。
更一般地说,任何以下形式的 for 循环都
与 while 循环完全相同:
for 循环更紧凑,因此更容易解析这种常见的习惯用法。
The loop is equivalent to:
As you can see from reading that code, it doesn't matter whether you use the post or pre decrement operator in the third section of the for loop.
More generally, any for loop of the form:
is exactly equivalent to the while loop:
The for loop is more compact, and thus easier to parse for such a common idiom.
为了可视化这些内容,请将 for 循环扩展为 while 循环:
扩展为:
对循环计数器进行后增量还是预增量并不重要,因为增量表达式的结果(之前或之后的值)增量)不在同一语句中使用。
To visualize these things, expand the for loop to a while loop:
Expands to:
Whether you do post-increment or pre-increment on the loop counter doesn't matter, because the result of the increment expression (either the value before or after the increment) isn't used within the same statement.
如果您关心的话,性能方面没有区别。仅当您在增量期间使用它时,它才会被错误使用(因此对错误敏感)。
考虑:
或者
然而,有趣的细节是,正常的习惯用法是在
for
语句的增量表达式中使用i++
,并且 Java 编译器将像一样编译它。使用++i
。There's no difference in terms of performance, if that's your concern. It can only be used wrongly (and thus sensitive to errors) when you use it during the increment.
Consider:
or
Interesting detail is however that the normal idiom is to use
i++
in the increment expression of thefor
statement and that the Java compiler will compile it as if++i
is used.++i 和 i++ 与赋值运算符(例如 int num = i++ 和 int num = ++i 或其他表达式)结合使用时会有所不同。
在上面的FOR循环中,只有递增条件,因为它不与任何其他表达式组合使用,所以没有任何区别。在这种情况下,它仅意味着 i = i + 1。
++i and i++ makes a difference when used in combination with the assignment operator such as int num = i++ and int num = ++i or other expressions.
In above FOR loop, there is only incrementing condition since it is not used in combination with any other expression, it does not make any difference. In this case it will only mean i = i + 1.
该循环与
while
循环相同:所以是的,它必须相同。
This loop is the same as this
while
loop:So yes, it has to be the same.
因为这个声明只是它自己的。增量的顺序在那里并不重要。
Because that statement is just on it's own. The order of the increment doesn't matter there.
这两种情况是等效的,因为 i 的值是在增量语句完成后进行比较的。然而,如果你这样做了
,
你就必须担心事情的顺序。
如果你
这样做了,那你就是疯了。
Those two cases are equivalent because the value of i is compared after the increment statement is done. However, if you did
versus
you'd have to worry about the order of things.
And if you did
then you're just nuts.
因为您的示例中没有任何内容使用从前增量或后增量返回的值。尝试在
++x
和x++
周围包裹一个System.out.println()
以查看差异。Because nothing in your examples is using the value returned from the pre- or post-increments. Try wrapping a
System.out.println()
around the++x
andx++
to see the difference.来自 Java 语言规范中有关 for 循环的章节< /a>:
(亮点是我的)。
From the Java Language Specification chapter on for loops:
(highlight is mine).
输出是相同的,因为“for(初始;比较;增量)”中的“增量”项不使用语句的结果,它仅依赖于方面 -语句的效果,在本例中是递增“i”,这在两种情况下是相同的。
The output is the same because the 'increment' item in the 'for (initial; comparison; increment)' doesn't use the result of the statement, it just relies on the side-effect of the statement, which in this case is incrementing 'i', which is the same in both cases.
因为
y
的值是在for
语句中计算的,x
的值是在它自己的行中计算的,但是在System中.out.println
它们仅被引用。如果您在 System.out.println 内递减,您将得到不同的结果。
Because the value of
y
is calculated infor
statement and the value ofx
is calculated in its own line, but in theSystem.out.println
they are only referenced.If you decremented inside
System.out.println
, you would get different result.检查是在计算增量参数之前完成的。 “增量”操作是在循环结束时完成的,即使它是在循环开始时声明的。
The check is done before the increment argument is evaluated. The 'increment' operation is done at the end of the loop, even though it's declared at the beginning.
试试这个例子:
你应该能够从中弄清楚它的作用。
Try this example:
You should be able to work out what it does from this.
这里有很多好的答案,但以防万一这有帮助:
将 y-- 和 --y 视为具有副作用的表达式,或一个语句后跟一个表达式。 y-- 就像这样(将这些示例视为伪汇编):
并且 --y 这样做:
在循环示例中,无论哪种方式,您都会丢弃返回的值,并且仅依赖于副作用(循环检查发生在递减语句执行之后;它不接收/检查递减返回的值)。
There are a lot of good answers here, but in case this helps:
Think of y-- and --y as expressions with side effects, or a statement followed by an expression. y-- is like this (think of these examples as pseudo-assembly):
and --y does this:
In your loop example, you are throwing away the returned value either way, and relying on the side effect only (the loop check happens AFTER the decrement statement is executed; it does not receive/check the value returned by the decrement).
如果
for
循环使用表达式i++
或++i
的结果来执行某些操作,那么它就是 true,但事实并非如此,它的存在只是因为它的副作用。这就是为什么您还可以在那里放置一个
void
方法,而不仅仅是一个数字表达式。If the
for
loop used the result of the expressioni++
or++i
for something, then it would be true, but that's not the case, it's there just because its side effect.That's why you can also put a
void
method there, not just a numeric expression.增量作为独立语句执行。所以
你——;
和
--y;
彼此等价,并且都等价于
y = y - 1;
The increment is executed as an independent statement. So
y--;
and
--y;
are equivalent to each other, and both equivalent to
y = y - 1;
因为:
编译器有效地将其翻译为:
如您所见,使用
y--
或--y
不会产生任何差异。不过,如果您像这样编写循环,则会产生不同的结果:这将产生与循环的两个变体相同的结果,但从
--y
更改为y--< /code> 这里会破坏你的程序。
Because this:
Effectively gets translated by the compiler to this:
As you see, using
y--
or--y
doesn't result in any difference. It would make a difference if you wrote your loop like this, though:This would yield the same result as your two variants of the loop, but changing from
--y
toy--
here would break your program.这是一个品味问题。他们做同样的事情。
如果您查看 java 类的代码,您会看到带有后增量的 for 循环。
It's a matter of taste. They do the same things.
If you look at code of java classes you'll see there for-loops with post-increment.
就你而言,它是相同的,没有任何区别。
in your case, it's the same, no difference at all.
你是对的。在本例中可以看出差异:
You are right. The difference can be seen in this case:
是的,它是按顺序执行的。初始化,然后评估条件,如果为真则执行主体,然后递增。
仅当您使用增量/减量进行赋值操作时,前缀和后缀的差异才会明显。
Yes it does it sequentially. Intialisation, then evaluation condition and if true then executing the body and then incrementing.
Prefix and Postfix difference will be noticable only when you do an Assignment operation with the Increment/Decrement.
没有区别,因为 for“参数”的每个部分都是单独的语句。
有趣的是,编译器可以决定用预增量替换简单的后增量,这不会改变代码。
There is no differences because every part of the for "arguments" are separated statements.
And an interesting thing is that the compiler can decide to replace simple post-incrementations by pre-incrementations and this won't change a thing to the code.
他们的行为不一样。使用 i++ 的构造比使用 ++i 的构造稍慢,因为前者涉及返回 i 的旧值和新值。另一方面,后者只返回i的旧值。
然后,出于性能原因,编译器可能会施展一点魔法,将任何孤立的 i++ 更改为 ++i,但就原始算法而言,它们并不严格相同。
They DON'T behave the same. The construct with i++ is slightly slower than the one with ++i because the former involves returning both the old and the new values of i. On the other side, the latter only returns the old value of i.
Then, probably the compiler does a little magic and changes any isolated i++ into a ++i for performance reasons, but in terms of raw algorithm they are not strictly the same.
Stackoverflow 上有很多类似的帖子:
但是,您的问题似乎更通用,因为它不特定于任何语言或编译器。上述大多数问题都涉及特定的语言/编译器。
以下是一个概要:
i
是一个整数(const int
、int
等):i++
替换为++i
,因为它们在语义上是相同的,因此不会改变输出。这可以通过检查生成的代码/字节码来验证(对于 Java,我使用 jclasslib 字节码查看器)。因此,如果 C++ 中有一个类重写了后缀和前缀运算符(例如
std::iterator
),则这种优化很少(如果有的话)完成。总结一下:
for
循环的增量部分,您几乎总是需要前缀版本(即++i
)。++i
和i++
之间的编译器切换并不总是可以完成,但如果可以的话,它会尽力为您完成。There's many similar posts at Stackoverflow:
However, it seems your question is more generic because it's not specific to any language or compiler. Most of the above questions deal with a specific language/compiler.
Here's a rundown:
i
is an integer (const int
,int
, etc.):i++
with++i
, because they are semantically identical and so it doesn't change the output. this can be verified by checking the generated code / bytecode (for Java, I use the jclasslib bytecode viewer).So if you have a class in C++ that overrides the postfix and prefix operators (like
std::iterator
), this optimization is rarely, if ever, done.In summary:
for
loops, you almost always want the prefix version (i.e.,++i
).++i
andi++
can't always be done, but it'll try to do it for you if it can.在循环中,首先初始化,然后条件检查,然后执行,然后递增/递减。所以前/后递增/递减不会影响程序代码。
in a loop, first initialization, then condition checking, then execution, after that increment/decrement. so pre/post increment/decrement does not affect the program code.
关于 i++(后增量)与 ++i(前增量)@me:“在这两种情况下,都会对表达式进行求值,并且结果用于检查条件。在前增量的情况下,增量对于后增量,增量表达式也会增量变量,但它返回之前的值,因此,前增量与增量值进行比较,而后增量与增量值进行比较。原始值;在这两种情况下,检查条件时变量都会增加。” – tdammers
About i++ (post-incrementation) vs. ++i (pre-incrementation) @me: "In both cases, the expression gets evaluated, and the result is used to check against the condition. In the pre-increment case, the increment expression increments the variable and returns the resulting value. For post-increment, the increment expression also increments the variable, but it returns the previous value. As a result, pre-increment compares against the incremented value, whereas post-increment compares against the original value; in both cases, the variable has been incremented when the condition is checked." – tdammers