C++ 前置インクリメントと後置インクリメント

インクリメント、デクリメントとは?

インクリメント(++演算子)は、val+=1 と等価。
デクリメント(--演算子)は、val-=1 と等価。
いずれも前置と後置が可能。

前置と後置の違い

見た目は似ているが、使い方を誤ると、
発見しにくいバグを生み出してしまうため注意が必要。

前置、後置の動作確認プログラム

int main()
{
    int a=0;
    int b=0;

    // 前置インクリメント
    b=++a;
    cout << "前置 a:" << a << endl;
    cout << "前置 b:" << b << endl;

    // 後置インクリメント
    b=a++;
    cout << "後置 a:" << a << endl;
    cout << "後置 b:" << b << endl;

    return 0;
}

実行結果

前置 a:1
前置 b:1
後置 a:2
後置 b:1


実行結果を見ると、前置と後置で結果が異なっている。
結果を見る限りでは、変数を単にインクリメントする分には、
前置、後置どちらでも構わないが、
インクリメント結果を代入する場合には注意が必要そうだ。

なぜ結果が異なるのか?

かの有名な!?「プログラミング言語C++」にはこう書かれている。

前置インクリメントについては、

y=++x は y=(x=x+1) と等価である。

要するに、+1した結果を代入している。

それに対し、後置インクリメントについては、

y=x++ は y=(t=x,x=x+1,t) と等価だ。

要するに、インクリメントする前の情報を代入している。

C++開発者が言っていることなので間違いはないだろう。

C++ これぞ参照の真骨頂!vector の要素を編集する

これは面白い!と思ったので記事にしてみる。
参照を使えばスマートに vector の要素を編集できる。

#include <iostream>
#include <vector>

using namespace std;

void TestFunc(vector<int>& v)
{
    for (int& x : v)
        ++x;
}

void PrintFunc(vector<int>& v)
{
    cout << "PrintFunc Start" << endl;
    for (int& x : v)
        cout << "v:" << x << endl;
}

int main()
{
    int ret = 0;
    vector<int> v = {1,2,3,4,5};

    PrintFunc(v);

    // vector の要素全てをインクリメント
    TestFunc(v);
    
    PrintFunc(v);

    return ret;
}
PrintFunc Start
v:1
v:2
v:3
v:4
v:5
PrintFunc Start
v:2
v:3
v:4
v:5
v:6

よく考えれば当然のことだが、目からウロコが落ちた。
vector の要素を直接編集できるってなんだか面白い。

Mac + VSCode + code-runner + g++ で C++11、C++14、C++17を実行する

Mac + VSCode + code-runner + g++ で C++11、C++14、C++17を実行する

実行環境をすぐに忘れてしまうので備忘録。

Mac にインストールしたパッケージ

  • Homebrew
  • g++

settings.json (VSCode) の設定

setting.json は下記の方法で編集する。

[Code] - [基本設定] - [設定] - [setting.json で編集]

setting.json には下記の記述を追加する。
C++ 以外の記述は省略

{
    "code-runner.executorMap": {
        "cpp": "cd $dir && runFiles=`ls *.cpp` && g++ -std=c++11 `echo ${runFiles}` -o $fileNameWithoutExt && $dir$fileNameWithoutExt",
    },
    "clang.cxxflags": ["-std=c++11"]
}

c++14、c++17をコンパイルする場合は、上記の「c++11」を対応バージョンに変更する。