今回は、C++での「i++ と ++i の違い(前置・後置インクリメント)」について解説していきます。
「i++と++iって何が違うの?」「どっちを使えばいいの?」と疑問に思ったことはありませんか?
この記事を読み終えると、あなたはインクリメントとデクリメントの前置・後置の違いを理解し、正しく使い分けられるようになると思いますので、ぜひ最後まで読んでいただけると嬉しいです。
インクリメント・デクリメントとは?
インクリメントとは、変数の値を1増やす操作です。
デクリメントとは、変数の値を1減らす操作です。
そして、演算子を変数の前に置くか後ろに置くかで、動作が変わります。
i++:後置インクリメント(使ってから増やす)++i:前置インクリメント(増やしてから使う)i--:後置デクリメント(使ってから減らす)--i:前置デクリメント(減らしてから使う)
後置インクリメント(i++)
後置インクリメントi++は、現在の値を使った後に、1増やすという動作をします。
▼main.cpp
#include <iostream>
int main() {
int i = 5;
int result = i++; // 現在の値(5)をresultに代入してから、iを6にする
std::cout << "result: " << result << "\n";
std::cout << "i: " << i << "\n";
return 0;
}実行結果
result: 5
i: 6
resultには増える前の値(5)が入り、その後iが6になります。
前置インクリメント(++i)
前置インクリメント++iは、先に1増やしてから、その値を使うという動作をします。
▼main.cpp
#include <iostream>
int main() {
int i = 5;
int result = ++i; // iを6にしてから、その値をresultに代入
std::cout << "result: " << result << "\n";
std::cout << "i: " << i << "\n";
return 0;
}実行結果
result: 6
i: 6
iが先に6になってから、増えた後の値(6)がresultに入ります。
デクリメントも同じ
デクリメントも、前置と後置で同じように動作します。
▼main.cpp
#include <iostream>
int main() {
int a = 5;
int b = 5;
int result1 = a--; // 後置:使ってから減らす
int result2 = --b; // 前置:減らしてから使う
std::cout << "result1: " << result1 << ", a: " << a << "\n";
std::cout << "result2: " << result2 << ", b: " << b << "\n";
return 0;
}実行結果
result1: 5, a: 4
result2: 4, b: 4
後置a--は減る前の値(5)を返し、前置--bは減った後の値(4)を返します。
単独で使う場合は同じ
変数を単独で増減させるだけなら、前置も後置も結果は同じです。
▼main.cpp
#include <iostream>
int main() {
int a = 5;
int b = 5;
a++; // 単独使用
++b; // 単独使用
std::cout << "a: " << a << "\n";
std::cout << "b: " << b << "\n";
return 0;
}実行結果
a: 6
b: 6
どちらも最終的に6になります。
forループでよく見るi++も、実は++iでも同じ結果になります。
▼main.cpp
#include <iostream>
int main() {
// どちらも同じ動作
for (int i = 0; i < 3; i++) {
std::cout << i << " ";
}
std::cout << "\n";
for (int i = 0; i < 3; ++i) {
std::cout << i << " ";
}
std::cout << "\n";
return 0;
}実行結果
0 1 2
0 1 2
違いが出る場面
前置と後置の違いがはっきり出るのは、他の式の中で使う時です。
配列のインデックスで使う場合
▼main.cpp
#include <iostream>
int main() {
int arr[] = {10, 20, 30};
int i = 0;
std::cout << "後置: " << arr[i++] << "\n"; // 10が表示され、iが1になる
std::cout << "i: " << i << "\n\n";
i = 0;
std::cout << "前置: " << arr[++i] << "\n"; // iが1になり、20が表示される
std::cout << "i: " << i << "\n";
return 0;
}実行結果
後置: 10
i: 1
前置: 20
i: 1
後置はarr[0]を使ってからi=1になり、前置はi=1にしてからarr[1]を使うという違いが出ます。
条件式の中で使う場合
▼main.cpp
#include <iostream>
int main() {
int count = 0;
// 後置:0のまま判定され、falseになる
if (count++) {
std::cout << "後置: true\n";
} else {
std::cout << "後置: false\n";
}
std::cout << "count: " << count << "\n\n";
count = 0;
// 前置:1になってから判定され、trueになる
if (++count) {
std::cout << "前置: true\n";
} else {
std::cout << "前置: false\n";
}
std::cout << "count: " << count << "\n";
return 0;
}実行結果
後置: false
count: 1
前置: true
count: 1
後置は増える前の値(0)で判定され、前置は増えた後の値(1)で判定されます。
パフォーマンスの違い
基本型(int、doubleなど)では、前置も後置も速度はほぼ同じです。
しかし、クラスのオブジェクトやイテレータでは、前置の方が効率的な場合があります。
▼理由
- 後置(
i++):元の値のコピーを作ってから増やす - 前置(
++i):直接増やすだけ
▼main.cpp
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
// イテレータでは前置の方が効率的
for (auto it = vec.begin(); it != vec.end(); ++it) {
std::cout << *it << " ";
}
std::cout << "\n";
return 0;
}そのため、特に理由がなければ前置(++i)を使う習慣をつけると良いとされています。
どちらを使うべき?
以下の基準で選びましょう。
| 状況 | 推奨 |
|---|---|
| 単独で使う場合(forループなど) | ++i(前置) |
| 増える前の値を使いたい | i++(後置) |
| 増えた後の値を使いたい | ++i(前置) |
| イテレータやクラスオブジェクト | ++i(前置) |
| 迷ったら | ++i(前置) |
基本的には前置(++i)を使い、後置の値が必要な時だけ後置(i++)を使うのが推奨されます。
注意点
同じ変数に対して、1つの式で複数回インクリメントするのは避けましょう。
▼main.cpp
#include <iostream>
int main() {
int i = 1;
// これは未定義動作!結果が予測できない
// int result = i++ + ++i;
// こう書くべき
int result = i;
i++;
result += i;
++i;
std::cout << "result: " << result << "\n";
std::cout << "i: " << i << "\n";
return 0;
}同じ式内で複数回変更すると、未定義動作となり、コンパイラによって結果が変わる可能性があります。
まとめ
前置と後置のインクリメント・デクリメントの違いをまとめます。
i++(後置):使ってから増やす++i(前置):増やしてから使う- 単独で使う場合は結果は同じ
- 他の式の中で使う場合に違いが出る
- 前置の方が効率的な場合があるため、迷ったら前置(++i)を使う
- 同じ式で複数回変更するのは避ける
これでインクリメント・デクリメントの前置と後置の違いはバッチリですね!
適切な方を選んで、バグの少ないコードを書いてみてください。
ここまで読んでくださり、ありがとうございました。
この記事が皆様の学習に役立てば幸いです。


