为什么在for循环的迭代部分不改变pre到post的增量会有所不同?

为什么这样呢

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循环的主体?

循环相当于:

 int x = 2; { int y = 2; while (y > 0) { System.out.println(x + " "+ y + " "); x++; y--; // or --y; } } 

从阅读该代码可以看出,在for循环的第三部分中使用post或pre decrement运算符无关紧要。

更一般地说,任何for循环的forms:

 for (ForInit ; Expression ; ForUpdate) forLoopBody(); 

完全等同于while循环:

 { ForInit; while (Expression) { forLoopBody(); ForUpdate; } } 

for循环更紧凑,因此更容易解析这种常见的习语。

要想象这些东西,请将for循环展开为while循环:

 for (int i = 0; i < 5; ++i) { do_stuff(i); } 

扩展到:

 int i = 0; while (i < 5) { do_stuff(i); ++i; } 

无论是对循环计数器进行后递增还是预递增都无关紧要,因为增量表达式的结果(在递增之前或之后的值)不在同一语句中使用。

如果这是您的关注,那么在性能方面没有区别。 增量期间 使用 ,它只能被错误地使用(因此对错误敏感)。

考虑:

 for (int i = 0; i < 3;) System.out.print(++i + ".."); //prints 1..2..3 for (int i = 0; i < 3;) System.out.print(i++ + ".."); //prints 0..1..2 

要么

 for (int i = 0; i++ < 3;) System.out.print(i + ".."); //prints 1..2..3 for (int i = 0; ++i < 3;) System.out.print(i + ".."); //prints 1..2 

然而,有趣的细节是,正常的习惯用法是在for语句的增量表达式中使用i++ ,并且Java编译器将编译它,就像使用++i

++ i和i ++与赋值运算符结合使用时会有所不同,例如int num = i ++和int num = ++ i或其他表达式。 在上面的FOR循环中,只有递增条件,因为它不与任何其他表达式结合使用,它没有任何区别。 在这种情况下,它只表示i = i + 1。

这个循环与while循环相同:

 int i = 0; while(i < 5) { // LOOP i++; // Or ++i } 

所以是的,它必须是一样的。

因为这个陈述就是它自己的。 增量的顺序在那里并不重要。

这两种情况是等价的,因为在增量语句完成后比较i的值。 但是,如果你这样做了

 if (i++ < 3) 

 if (++i < 3) 

你必须担心事情的顺序。

如果你这样做了

 i = ++i + i++; 

那你就疯了。

因为您的示例中没有任何内容使用从增量前或后增量返回的值。 尝试围绕++xx++包装System.out.println()以查看差异。

从for循环中的Java语言规范章节 :

BasicForStatement:

  for ( ForInit ; Expression ; ForUpdate ) Statement 

…如果存在ForUpdate部分,则从左到右依次计算表达式; 它们的值(如果有的话)被丢弃。 …如果ForUpdate部件不存在,则不执行任何操作。

(突出显示是我的)。

输出是相同的,因为’for(initial; comparison; increment)’中的’increment’项不使用语句的结果 ,它只依赖于语句的副作用 ,在这种情况下是递增’i’,这两种情况都是一样的。

在评估增量参数之前完成检查。 ‘increment’操作在循环结束时完成,即使它在开头声明。

试试这个例子:

 int i = 6; System.out.println(i++); System.out.println(i); i = 10; System.out.println(++i); System.out.println(i); 

你应该能够弄清楚它的作用。

因为y的值是在for语句中计算的, x的值是在它自己的行中计算的,但是在System.out.println它们只被引用。

如果在System.out.println递减,则会得到不同的结果。

 System.out.println(y--); System.out.println(--y); 

这里有很多好的答案,但如果这有帮助:

将y–和-y视为具有副作用的表达式,或者后跟表达式的语句。 y–是这样的(把这些例子想象成伪assembly):

 decrement y return y 

而且 – 这样做:

 store y into t decrement y load t return t 

在循环示例中,您将丢弃返回的值,并且仅依赖于副作用(循环检查在执行递减语句之后发生;它不接收/检查递减返回的值)。

如果for循环使用了表达式i++++i的结果,那么它就是真的,但事实并非如此,只是因为它的副作用。

这就是为什么你也可以在那里放一个void方法,而不仅仅是一个数值表达式。

增量作为独立语句执行。 所以

y–;

–y;

相当于彼此,两者相当于

y = y – 1;

因为这:

 int x = 2; for (int y =2; y>0; y--){ System.out.println(x + " "+ y + " "); x++; } 

编译器有效地将其翻译为:

 int x = 2; int y = 2 while (y > 0){ System.out.println(x + " "+ y + " "); x++; y--; } 

如您所见,使用y----y不会产生任何差异。 如果你像这样编写你的循环会有所不同:

 int x = 2; for (int y = 3; --y > 0;){ System.out.println(x + " "+ y + " "); x++; } 

这将产生与循环的两个变体相同的结果,但是从--y变为y--这将破坏您的程序。

这是一个品味问题。 他们做同样的事情。

如果你看一下java类的代码,你会看到带有post-increment的for循环。

在你的情况下,它是相同的,没有任何区别。

你是对的。 在这种情况下可以看出差异:

 for(int i = 0; i < 5; ) { System.out.println("i is : " + ++i); } 

是的它按顺序执行。 初始化,然后是评估条件,如果是,则执行正文然后递增。

只有在使用递增/递减进行分配操作时,才会显示前缀和后缀差异。

没有区别,因为“参数”的每个部分都是分开的语句。

有趣的是,编译器可以决定通过预增量替换简单的后增量,这不会改变代码。

他们的行为不一样。 使用i ++的构造比使用++ i的构造略慢,因为前者涉及返回i的旧值和新值。 另一方面,后者只返回i的旧值。

然后,由于性能原因,编译器可能会做一点魔术并将任何隔离的i ++更改为++ i ,但就原始算法而言,它们并不完全相同。

Stackoverflow上有很多类似的post:

  • 循环中i ++和++ i之间的区别?
  • C#中的++ i和i ++之间是否存在任何性能差异?
  • C ++中的i ++和++ i之间是否存在性能差异?

但是,似乎您的问题更通用,因为它并不特定于任何语言或编译器。 上述大多数问题都涉及特定的语言/编译器。

这是一个纲要:

  • 如果我们谈论C / C ++ / Java(可能也是C#)和现代编译器:
    • 如果i是一个整数( const intint等):
      • 然后编译器基本上用++i替换i++ ,因为它们在语义上是相同的,所以它不会改变输出。 这可以通过检查生成的代码/字节码来validation(对于Java,我使用jclasslib字节码查看器 )。
    • 其他:
  • 其他:
    • 所有的赌注都是关闭的,因为编译器不能保证它们在语义上是相同的,所以它不会尝试优化。

因此,如果你有一个C ++类,它会覆盖后缀和前缀运算符(比如std::iterator ),那么这种优化很少(如果有的话)完成。

综上所述:

  • 意思是你说什么,说出你的意思。 对于for循环的增量部分,您几乎总是需要前缀版本(即++i )。
  • ++ii++之间的编译器切换器并不总是可以完成,但是如果可以的话,它会尝试为你做。

在循环,首次初始化,然后条件检查,然后执行,在增加/减少之后。 所以前/后递增/递减不会影响程序代码。

关于i ++(增量后)与++ i(预增量)@me:“在这两种情况下,表达式都会被计算,结果用于检查条件。在预增量的情况下,增量表达式增加变量并返回结果值。对于后增量,增量表达式也会增加变量,但它会返回先前的值。因此,预增量与增量值进行比较,而后增量则与增量值进行比较。原始值;在这两种情况下,当检查条件时变量已经增加。“ – tdammers

在post和pre increment操作符之间存在相当混乱,这可以从“算法,Robert Sedgewick和Kevin Wayne的第4版”摘录中轻松理解。

递增/递减运算符:i ++与i = i + 1相同,并且在表达式中具有值i。 类似地,i–与i = i – 1相同。代码++ i和 – i是相同的,除了表达式值是在递增/递减之后,而不是之前。

例如

 x = 0; post increment: x++; step 1: assign the old value (0) value of the x back to x.So, here is x = 0. step 2: after assigning the old value of the x, increase the value of x by 1. So, x = 1 now; when try to print somthing like: System.out.print(x++); the result is x : 0. Because only step one is executed which is assigning old value of the x back and then print it. But when, we do operation like this: i++; System.out.print(i); the result is x: 1. which is because of executing Step one at first statement and then step two at the second statement before printing the value. pre increment: ++x; step 1: increase the value of x by 1. So, x = 1 now; step 2: assign the increased value back to x. when try to print something like: System.out.print(++1) the result is x : 1. Because the value of the x is raised by 1 and then printed. So, both steps are performed before print x value. Similarly, executing ++i; system.out.print(i); Both steps are executed at statement one. At second statement, just the value of "i" is printed.