51
42

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

C++では、必要でない限り、後置インクリメント演算子は使わず、前置インクリメント演算子を使ったほうがよい

Last updated at Posted at 2015-09-17

現在C++を勉強しようと、『C++ Primer, 5th Edition』を読んでいるのですが、Javaからプログラミングに入った身として、Javaとは違う慣習をいくつか発見しました。その中の一つが、 必要でない限り、後置インクリメント演算子は使わず、前置インクリメント演算子を使う ことです。

例えばよく使う以下のようなforループでは、Javaプログラマーとしてはこう書いてしまいがちですが、
for (int i = 0; i < n; i++)

C++的にはこう書いたほうが良いようです。
for (int i = 0; i < n; ++i)

(本当はC++的にはi != nと書いた方が良いようですが、それはまた別の話なので分かりやすくするため、あえて変えませんでした)

理由

理由としては、前置バージョンの場合、単純に被演算子をインクリメントしたあと、変更されたオブジェクトを結果として取得しますが、後置バージョンの場合、被演算子をインクリメントしたあと、 変更される前の元のコピーを取得 します。その結果、後置バージョンの方が処理が多くなってしまいます。コンパイラによりこの辺の処理が最適化してあったりもするようですが、intなどでなく、複雑なイテレータの型の場合、処理が高まる場合もあるようです。

追記 (2016/01/02):
@MoriokaReimenさんによるgccでのint型を使った検証の結果 (コメント参照)、吐き出されるアセンブリコードに違いは現れなかったそうです。最近のコンパイラではプリミティブ型の場合、前置バージョンと後置バージョンによる処理の違いはないと考えてよさそうです。

追記 (2018/06/18):
@fujitanozomuさんによる初期C++コンパイラであるTurbo C++ Version 1.01による検証の結果(コメント参照)でも、ほぼ違いがでなかったそうです。古いコンパイラでもプリミティブ型の場合、大きな違いは出ないようです。

追記(2020/02/18):
@hanazino17 さんによる補足

代入する場合はインクリメントが先か代入が先かという違いがあります。
効率の話はコピーコンストラクタが何回動くかの話です。
プリミティブ型はコンストラクタはないので当然アセンブリに差はでないです。
どちらが良いとかではなく、必要に応じて使い分けるのが正しい理解だと思います。

感想

細かい違いですが、C++のような低級な言語では、こういった細かいところでの最適化が大事になってくると思うので、気をつけていきたいと思います。

参考文献

C++ Primer, 5th Edition (p.148より)

51
42
9

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
51
42

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?