【C++】i++(後置インクリメント)と++i(前置インクリメント)の違いとは?|わかりやすく解説

サムネイル画像 C++

今回は、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)を使う
  • 同じ式で複数回変更するのは避ける

これでインクリメント・デクリメントの前置と後置の違いはバッチリですね!

適切な方を選んで、バグの少ないコードを書いてみてください。

ここまで読んでくださり、ありがとうございました。

この記事が皆様の学習に役立てば幸いです。