※本記事はSekappy社内で実施したアドベントカレンダーに投稿されたものです。
基本のおさらい
インクリメント/デクリメント演算に馴染みが無い方もいるかもしれないので、簡単に要約します。
-
インクリメント演算子(++) — 変数の値を1増やす
-
デクリメント演算子(--) — 変数の値を1減らす
また、演算子を変数の前に書く前置演算と、変数の後に書く後置演算で挙動が異なります。 -
前置演算(++a) — 変数aを1加算した後、aの値を返す
-
後置演算(a++) — 変数aの値を返した後、aを1加算する
主要プログラミング言語でのインクリメント/デクリメントの有無
| 有り | C言語、C++、C#、Java、Kotlin、JavaScript、PHP、Dart、Go(注1) |
| 無し | Python、Ruby、VisualBasic、Rust、Swift(注2) |
【注1】Goの言語仕様
Goではインクリメント/デクリメントは式ではなく文(statement)と定義されています。(参考)
++/-- はありますが、言語仕様上これらは演算子ではありません。
したがって以下のように計算結果を代入するようなコードは書けません。
y = x++ //NG!
また、式ではないため前置/後置という概念も無く、++/-- は変数の後ろにのみ記載可能です。
【注2】Swiftの言語仕様
初期のSwiftにはインクリメント/デクリメントが存在しましたが、Swift 3のリリースの際に廃止されました。
廃止された詳しい理由についてはこちらをご覧ください。
(原文は英語ですが、日本語に機械翻訳すれば大体の内容は分かります)
【余談】JSLintにおけるインクリメント/デクリメント
JavaScriptにはインクリメント/デクリメントが存在しますが、最初期の静的解析ツール「JSLint」をデフォルト設定で使用すると、++/-- の使用箇所に対して警告が出ます。
これはJSLintの作者であるDouglas Crockford氏の意向によるもので、理由は後述の「インクリメント/デクリメント演算が実装されなかった理由」とほぼ同じです。
インクリメント/デクリメント演算が実装されなかった理由
前述の通り、いくつかのプログラミング言語ではインクリメント/デクリメント演算は実装されていません。
実装を見送った理由は色々とありますが、よく目にする意見は以下の3点です。
- 可読性の低下
- 式に ++/-- が埋め込まれていると可読性を損なう。
- トリッキーなコードを書いて混乱を招く恐れがある。
- 煩雑さ
- プログラミング初学者にとっては ++/-- 演算子の存在や前置/後置の挙動の違いが、学習の負担になる。
- 利点が乏しい
- ++/-- は多くの場合 +=1, -=1 で代替可能であり、あえてこの演算子を使用しなければならないケースは少ない。
インクリメント/デクリメント演算を使用する利点
昔の処理系においては、コードを機械語に変換する際に加算命令(ADD)/減算命令(SUB)ではなく、処理効率の良いインクリメント命令(INC)/デクリメント命令(DEC)への変換を明示する意図がありました。
【ADD命令で1を加算する場合 — 2ステップ、2レジスタ使用】
MOV AX,1 ;AX=1
ADD BX,AX ;BX=BX+AX
【INC命令で1を加算する場合 — 1ステップ、1レジスタのみ使用】
INC BX ;BX=BX+1
しかし、現代の処理系では多くの場合、上記のようなケースは適切な最適化が行われるようになりました。コード実装者がこの点を意識する必要も、ほぼなくなったと言えるでしょう。
それ以外の利点としては……コードが多少簡潔になるというくらいでしょうか(汗
a = a + 1;
a += 1;
a++; //上2行よりちょっとだけ短い!!
インクリメント/デクリメントの使用が避けられないケース
演算子のオーバーロード(多重定義)が可能なC++、C#、Kotlinなどの言語では、++/-- を使用しないと期待した結果が得られないケースがあります。
この点については使用言語の仕様や、使用するライブラリ・プラグインの仕様を確認し、適宜 ++/-- 演算子を使用する必要があります。
結局のところインクリメント/デクリメントの使用は避けるべきなのか?
インクリメント/デクリメントの使用についてネガティブ寄りの内容になってしまいましたが、使用の是非に関しては、結局は開発チームのコーディング規約次第です。
しかし、かつては当たり前のように実装されていたインクリメント/デクリメント演算が、近年のプログラミング言語では実装を見送られている現状を踏まえると、使用に際してはしっかりとした意図を持つことが必要かもしれません。