1. 序章
このチュートリアルでは、ループのプリインクリメント演算子とポストインクリメント演算子の違いについて説明します。
2. プレインクリメントとポストインクリメント
Java やCなどの多くのプログラミング言語は、インクリメント前およびインクリメント後の演算に特化した単項演算子を提供します:()および()。 どちらも引数変数を1ずつ増やしますが、同じ方法ではありません。
特に、 x が整数変数であり、それをより大きな式の一部として事前にインクリメントする場合、プログラムは最初に x に1を加算し、次にを評価します。式全体の評価の一部として、xを新しい値に変更します。 例えば:
int x = 4;
int y = (++x) + 100;
// x = 5, y = 105
対照的に、ポストインクリメントの選択肢は x をインクリメントしますが、式内の古い値に評価します。 式が評価された後でのみ、xは新しい値を持ちます。
int x = 4;
int y = (x++) + 100;
// x = 5, y = 104
ご覧のとおり、どちらの場合も x = 5 ですが、yの最終的な値は異なります。
3. ループ内のプリインクリメントとポストインクリメント
ループ内でこれらの操作を使用する方法を分析してみましょう。 カウンターが増えるループに焦点を当てます。
3.1. ループの一般的な形式
各カウンターベースのループは、次のように指定されます。
- そのカウンターの初期値
- 終了条件
- 増分ステップ
- とループの本体
概略的に:
終了テストとインクリメントステップを別々に実行する場合は、どの演算子を使用してカウンターを増やすかは関係ありません。 結果は同じになります。
ただし、終了条件テストに増分操作が含まれている場合、2つの選択肢によって異なる結果が生じる可能性があります。
3.2. ポストインクリメントによる条件のテスト
1からまでのすべての数値を出力したいとします。 ポストインクリメント演算子を使用すると、次のようなことを試すことができます。
このループはどのように展開しますか?
まず、0に設定します。 次に、かどうかをテストし、直後に更新して状態を確認します。 更新に続いて、ループの本体を実行します。
次に、反復を繰り返します。 条件をテストします。 以来、printステートメントに設定して次に進みます。
テストの直前までこのように続けます。 ポストインクリメント演算子を使用しているため、の現在の値を使用して条件を確認し、それに1を追加します。 したがって、チェックの前から、、はテストに合格します。つまり、ループの本体を実行します。 テスト後に更新されたカウンターを使用するため、を出力します。 その後、状態に戻ります。 なので、ループを停止します。
問題は、数字だけが必要なのに印刷していることです。
したがって、条件をまたはに変更する必要があります。 残念ながら、それは少し直感に反します。 またはでテストした場合、ループに10という数字を含めたいかどうかはすぐにはわかりません。 の条件はより理にかなっています。
3.3. プレインクリメントを使用した条件のテスト
pre-increment演算子を使用するようにループを書き直してみましょう。 例えば:
このループには含まれますか? さて、最初にインクリメントしてから、その新しい値がであるかどうかを確認するので、最後に出力する数値はになります。 次の反復では、はfalseと評価されるため、ループを終了します。
3.4. 読みやすさ
コードが読みにくくなるため、増分ステップと終了チェックを結合することはお勧めできません。前の例で両方のループを機能させたとしても、最後の数値と正しい定式化について考える必要がありました。停止基準の。
また、正しいですが、上記のループには直感的な初期化ステップがありません。 どちらもカウンターをとして初期化します。 ループを徹底的に分析するまで、ほとんどの人は0を出力すると思います。 対照的に、テストとインクリメントのステップが分離されたループと混同することはありません:
その意味はすぐに明らかになります。 一般的に、私たちはそのようなレベルの読みやすさを目指して努力する必要があります。
3.5. インクリメントステップ
前に述べたように、プリインクリメント演算子とポストインクリメント演算子は、カウンターを増やすために使用するときに、ループのセマンティクスと正確さに影響を与えません。
ただし、 C ++ などの一部のオブジェクト指向言語では、クラスに演算子を実装できます。 ループのカウンターなどのオブジェクトを使用すると、インクリメント後の代替案の実行がインクリメント前の代替案よりも遅くなることがあります。
その理由は、増分しますが古い値を返すためです。 したがって、に参加する式全体を評価するまで、新しい値を格納する必要があります。 ループの複雑さは変わりませんが、が複雑なオブジェクトの場合、各増分ステップでの内容をコピーするため、実行速度が低下する可能性があります。
4. 結論
この記事では、ループの終了条件内でのプリインクリメント演算子とポストインクリメント演算子の違いについて説明しました。
経験則として、コードを読みやすくするために、増分ステップを終了条件テストから切り離す必要があります。