Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

現在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より)

tommy6073
レールの無い道を行くプログラマー
https://www.okweird.net
pepabo
「いるだけで成長できる環境」を標榜し、エンジニアが楽しく開発できるWebサービス企業を目指しています。
https://pepabo.com
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away