なぜこれなのか
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またはpredecrement演算子を使用するかどうかは関係ありません。
より一般的には、次の形式の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;
}
インクリメント式の結果(インクリメントの前または後の値)は同じステートメント内で使用されないため、ループカウンターでポストインクリメントを行うかプレインクリメントを行うかは重要ではありません。
それがあなたの懸念であるならば、パフォーマンスの点で違いはありません。 use it duringインクリメントする場合にのみ、誤って使用できます(したがってエラーの影響を受けやすくなります)。
考えてみましょう:
_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 ++やintnum = ++ iなどの代入演算子やその他の式と組み合わせて使用すると違いが生じます。上記のFORループでは、他の式と組み合わせて使用されないため、インクリメント条件のみがあり、違いはありません。この場合、それはi = i +1のみを意味します。
このループは、このwhile
ループと同じです。
int i = 0;
while(i < 5)
{
// LOOP
i++; // Or ++i
}
そうです、それは同じでなければなりません。
その声明はそれ自体のものだからです。増分の順序はそこでは重要ではありません。
インクリメントステートメントが実行された後にiの値が比較されるため、これら2つのケースは同等です。しかし、あなたがした場合
if (i++ < 3)
versus
if (++i < 3)
あなたは物事の順序について心配しなければならないでしょう。
そして、あなたがした場合
i = ++i + i++;
その後、あなたはただのナッツです。
あなたの例には何もないのでsing pre-またはpost-incrementsから返される値。 System.out.println()
を++x
とx++
でラップして、違いを確認してください。
BasicForStatement:
for ( ForInit ; Expression ; ForUpdate ) Statement
... ForUpdate部分が存在する場合、式は左から右に順番に評価されます。 それらの値がある場合は破棄されます。... ForUpdate部分が存在しない場合、アクションは実行されません。
(ハイライトは私のものです)。
「for(初期;比較;インクリメント)」の「インクリメント」項目はステートメントの結果を使用せず、サイド)に依存しているため、出力は同じです。 -effectステートメントの。この場合は「i」をインクリメントします。これは両方の場合で同じです。
この例を試してください:
int i = 6;
System.out.println(i++);
System.out.println(i);
i = 10;
System.out.println(++i);
System.out.println(i);
あなたはそれがこれから何をするかを理解することができるはずです。
チェックは、インクリメント引数が評価される前に実行されます。 'increment'操作は、最初に宣言されていても、ループの最後で実行されます。
y
の値はfor
ステートメントで計算され、x
の値は独自の行で計算されるため、System.out.println
では参照されるだけです。
System.out.println
内でデクリメントすると、異なる結果が得られます。
System.out.println(y--);
System.out.println(--y);
for
ループが式i++
または++i
の結果を何かに使用した場合、それは真になりますが、そうではありません。副作用があるという理由だけで存在します。
そのため、数式だけでなく、void
メソッドを配置することもできます。
ここには良い答えがたくさんありますが、これが役立つ場合:
Y--および--yは、副作用のある式、またはステートメントの後に式が続くものと考えてください。 y--は次のようなものです(これらの例を疑似アセンブリと考えてください):
decrement y
return y
そして--yはこれを行います:
store y into t
decrement y
load t
return t
ループの例では、どちらの方法でも戻り値を破棄し、副作用のみに依存しています(ループチェックは、デクリメントステートメントの実行後に発生します。デクリメントによって返された値を受信/チェックしません)。
For "arguments"のすべての部分が別々のステートメントであるため、違いはありません。
そして興味深いのは、コンパイラーが単純なポストインクリメントをプレインクリメントに置き換えることを決定できることです。これによってコードが変わることはありません。
インクリメントは独立したステートメントとして実行されます。そう
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++;
}
これにより、ループの2つのバリアントと同じ結果が得られますが、ここで--y
からy--
に変更すると、プログラムが破損します。
I ++(ポストインクリメント)と++ i(プレインクリメント)について@me: "どちらの場合も、式が評価され、その結果を使用して条件をチェックします。プレインクリメントの場合、インクリメント式は変数をインクリメントし、結果の値を返します。ポストインクリメントの場合、インクリメント式も変数をインクリメントしますが、前の値を返します。その結果、プリインクリメントはインクリメントされた値と比較され、ポストインクリメントは元の値。どちらの場合も、条件がチェックされると変数がインクリメントされます。」 – tdammers
ポストインクリメント演算子とプリインクリメント演算子の間にはかなりの混乱があります。これは、この「アルゴリズム、ロバートセッジウィックとケビンウェインによる第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.
Stackoverflowには同様の投稿がたくさんあります。
ただし、どの言語やコンパイラにも固有ではないため、質問はより一般的であるように思われます。上記の質問のほとんどは、特定の言語/コンパイラを扱っています。
要約は次のとおりです。
i
が整数の場合(const int
、int
など):i++
を++i
に置き換えます。これは、これらが意味的に同一であり、出力を変更しないためです。これは、生成されたコード/バイトコードをチェックすることで確認できます(Javaの場合、 jclasslibバイトコードビューア を使用します)。したがって、C++に、接尾辞と接頭辞の演算子(std::iterator
など)をオーバーライドするクラスがある場合、この最適化が行われることはほとんどありません。
要約すれば:
for
ループのインクリメント部分では、ほとんどの場合、プレフィックスバージョン(つまり、++i
)が必要です。++i
とi++
の間のコンパイラの切り替えは、常に実行できるとは限りませんが、可能であれば、それを実行しようとします。ループでは、最初に初期化、次に条件チェック、次に実行、その後インクリメント/デクリメントします。したがって、プリ/ポストインクリメント/デクリメントはプログラムコードに影響を与えません。
それらは同じように動作しません。 i ++の構成は、++ iの構成よりもわずかに遅くなります。これは、前者がiの古い値と新しい値の両方を返す必要があるためです。一方、後者はiの古い値のみを返します。
次に、おそらくコンパイラは少し魔法をかけ、パフォーマンス上の理由から、分離されたi ++を++ iに変更しますが、生のアルゴリズムに関しては、厳密には同じではありません。
あなたが正しいです。この場合、違いがわかります。
for(int i = 0; i < 5; )
{
System.out.println("i is : " + ++i);
}
それは好みの問題です。彼らは同じことをします。
Javaクラスのコードを見ると、ポストインクリメントのforループがあります。
あなたの場合、それは同じで、まったく違いはありません。
はい、順番に行います。初期化、次に評価条件、そしてtrueの場合、本体を実行してからインクリメントします。
プレフィックスとポストフィックスの違いは、インクリメント/デクリメントを使用して割り当て操作を実行した場合にのみ顕著になります。