これはなぜですか
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ループの3番目のセクションでpost演算子またはpre-decrement演算子を使用するかどうかは関係ありません。
より一般的には、次の形式のforループです。
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
面白い詳細は、しかし、通常の慣用句が使用することですi++
のインクリメント式でfor
文と、Javaコンパイラが次のようにコンパイルします。++i
使用されている。
++ iとi ++は、int num = i ++やint num = ++ iなどの代入演算子、またはその他の式と組み合わせて使用すると効果があります。 上記のFORループでは、他の式と組み合わせて使用されていないため、増分条件のみが存在し、違いはありません。この場合、それはi = i + 1を意味するだけです。
for(int i = 0; i < 10; doSomething(i++))
またはfor(i = -1; ++i < 10;)
プレインクリメントまたはポストインクリメントで使用した場合、実際には違いがあります。つまり、アサーションは、完全にfor
ループ(最初の文でコンテキストを指定していないことを確認するためにもう一度読む)が間違っています。 - fortran
その記述はそれだけであるからです。増分の順序は関係ありません。
これら2つのケースは、インクリメントステートメントの実行後にiの値が比較されるため、同等です。しかし、あなたがした場合
if (i++ < 3)
対
if (++i < 3)
あなたは物事の順序を心配しなければならないでしょう。
そしてあなたがした場合
i = ++i + i++;
それならあなたはただナッツです。
あなたの例には何もないので使う前後の増分から返される値。ラッピングしてみてくださいSystem.out.println()
の周辺++x
そしてx++
違いを見るために。
BasicForStatement:
for ( ForInit ; Expression ; ForUpdate ) Statement
... ForUpdate部分が存在する場合、 式はで評価されます 左から右への順序。彼らの もしあれば、値は破棄されます。... ForUpdate部分が存在しない場合は、 何もしません。
(ハイライトは私のものです)。
'for(初期;比較;増分)'の '増分'項目では使用しないため、出力は同じです。結果声明のうち、それは副作用これは、この場合は 'i'を増分していますが、どちらの場合も同じです。
インクリメント引数が評価される前にチェックが行われます。 「インクリメント」操作は、たとえ冒頭で宣言されていても、ループの終わりで行われます。
この例を試してください:
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--はこのようなものです(これらの例を疑似アセンブリとして考えてください)。
decrement y
return y
そして--yはこれをします:
store y into t
decrement y
load t
return t
ループの例では、戻り値をどちらかの方法で破棄し、副作用のみに依存しています(ループチェックは、減少ステートメントが実行された後に行われます。減少によって返された値は受け取りません)。
あればfor
ループは式の結果を使用しましたi++
または++i
何かのために、それは本当だろうが、それは事実ではない、それはその副作用があるという理由だけでそこにある。
だからあなたも置くことができる理由void
そこにあるメソッドは、数値式だけではありません。
インクリメントは独立したステートメントとして実行されます。そう
そして
そして
--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++;
}
これは、ループの2つの変形と同じ結果になりますが、--y
にy--
これはあなたのプログラムを壊すでしょう。
それは好みの問題です。彼らは同じことをします。
Javaクラスのコードを見ると、ポストインクリメント付きのforループがあります。
あなたの場合、それは同じです、まったく違いはありません。
あなたが正しいです。この場合、違いがわかります。
for(int i = 0; i < 5; )
{
System.out.println("i is : " + ++i);
}
はいそれはそれを順次します。初期化、それから評価条件、そして真ならばボディを実行し、そしてインクリメントする。
接頭辞と接尾辞の違いは、Increment / Decrementを使ってAssignment操作を実行した場合にのみ顕著になります。
for "arguments"の各部分は別々のステートメントであるため、違いはありません。
そして興味深いことは、コンパイラーが単純な事後増分を事前増分で置き換えることを決めることができ、これがコードの事を変えることはないということです。
i += 1
結果はステートメントで使用されていないためです。 - Carlos Heubergeriinc
そしてそれは置き換えられますi++
、++i
そしてi += 1
。私はただコンパイラが++i
、i++
すべてのケースでステートメントから操作し、それをsimple iinc
元の文の前後に配置します。 - Colin Hebert
彼らは同じように振舞いません。以下のコンストラクトi ++あるものよりわずかに遅いです++ i前者は、の古い値と新しい値の両方を返すことを含むからです。私。一方、後者はの古い値のみを返します。私。
それから、おそらくコンパイラは少し魔法をかけ、分離されたものを変更します。i ++に++ iパフォーマンス上の理由から、生のアルゴリズムの観点からは、厳密には同じではありません。
for
ループケース?私の推測では、ほとんどのコンパイラは、i ++を++ iに変更するのに十分なほどインテリジェントであるということでしょう。 - PinINC
バイトコード。i += 1
。 - Carlos Heuberger
Stackoverflowにも同様の記事がたくさんあります。
しかし、それはあなたの質問がより一般的であるように思われます。なぜならそれはどの言語やコンパイラにも固有のものではないからです。上記の質問の大部分は特定の言語/コンパイラを扱います。
これが要約です。
i
整数です(const int
、int
など):i++
と++i
なぜなら、それらは意味的に同一であり、それゆえ出力を変更しないからです。これは、生成されたコード/バイトコードをチェックすることで確認できます(Javaの場合は、jclasslibバイトコードビューア)あなたがC + +で後置と前置演算子をオーバーライドするクラスを持っているのであれば(のようにstd::iterator
)、この最適化が行われたとしても、めったに行われません。
要約すれば:
for
ループする場合は、ほとんどの場合プレフィックスバージョンが必要です(つまり、++i
)++i
そしてi++
いつもできるわけではありませんが、可能であればあなたのためにやろうとします。
ループでは、最初の初期化、次に条件チェック、そして実行、そしてその増加/減少の後。そのため、前後の増分/減分はプログラムコードに影響しません。
i ++(ポストインクリメント)と++ i(インクリメント前)の比較@me: "どちらの場合も、式は評価され、結果は条件との照合に使用されます。プレインクリメントの場合はインクリメントポストインクリメントの場合、インクリメント式も変数をインクリメントしますが、前の値を返します結果として、プリインクリメントはインクリメントされた値と比較し、ポストインクリメントはその値と比較します。元の値、どちらの場合も、条件がチェックされたときに変数がインクリメントされています。」 - ダムマー
ポストインクリメント演算子とプリインクリメント演算子の間にはかなり混乱があります。これは、「Robert SedgewickとKevin Wayneによる第4版のアルゴリズム」の抜粋から容易に理解できます。
インクリメント/デクリメント演算子:i ++はi = i + 1と同じであり、値は 私は式で。同様に、i--はi = i - 1と同じです。 --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.