記事内にはプロモーションが含まれています

【C++】std::mapの初期化方法まとめ!リスト初期化から構造体メンバまで徹底解説

【C++】std::mapの初期化方法まとめ!リスト初期化から構造体メンバまで徹底解説 C++

C++の標準ライブラリ(STL)に含まれる std::map は、キーと値をペアで管理する連想配列として、設定データの管理や辞書的な用途で頻繁に利用されます。

しかし、C++には歴史的な経緯から複数の初期化記法が存在するため、「効率的で読みやすい初期化方法はどれか?」「クラスのメンバ変数として map を持つ場合、どう初期化すればいいのか?」と迷うことも少なくありません。

この記事では、std::map の基本的な初期化方法から、C++11以降の便利な初期化子リスト、構造体メンバとしての利用、そして「キーが存在しない場合のデフォルト値(0や空文字)」の挙動までを、サンプルコード付きで詳しく解説します。

【本記事の信頼性】
プロフィール
執筆者:マヒロ
  • 執筆者は元エンジニア
  • SES⇒大手の社内SE⇒独立
  • 現在はこじんまりとしたプログラミングスクールを運営
  • モットーは「利他の精神」

std::mapの基本的な初期化方法

C++で map を初期化する際、最も一般的で推奨されるのは 初期化子リスト(Initializer list) を使う方法です。

これにより、宣言と同時にデータを投入でき、コードが非常に簡潔になります。

初期化子リストを使った宣言と代入(C++11以降)

波括弧 {} を使って、キーと値のペアを列挙します。

#include <iostream>
#include <map>
#include <string>

int main() {
    // stringがキー、intが値のmapを初期化
    std::map<std::string, int> scores = {
        {"Alice", 100},
        {"Bob", 85},
        {"Charlie", 90}
    };

    // 出力して確認
    // C++17以降の「構造化束縛」を使うとスッキリ書ける
    for (const auto& [name, score] : scores) {
        std::cout << name << ": " << score << std::endl;
    }

    return 0;
}

実行結果

Alice: 100
Bob: 85
Charlie: 90

std::map<std::string, int> scores = { ... }; という構文で、宣言と同時にデータを格納しています。
内側の {} がそれぞれのペア(std::pair)を表しています。

C++17以降では、for (const auto& [key, val] : map) のような「構造化束縛」を使うことで、イテレータを使わずにスマートに要素を取り出すことが可能です。

空のmapを宣言する場合

データは後から追加するため、最初は空の状態にしておきたい場合は、引数なしで宣言します。

#include <iostream>
#include <map>
#include <string>

int main() {
    // 空のmapを作成
    std::map<int, std::string> productList;

    // この時点ではサイズは0
    if (productList.empty()) {
        std::cout << "Map is empty." << std::endl;
    }

    return 0;
}

実行結果

Map is empty.

特に特別な記述は必要ありません。
デフォルトコンストラクタが呼ばれ、要素数0の状態で生成されます。

別のmapからコピーして初期化する

既存の map と同じ内容を持つ新しい map を作りたい場合は、コピーコンストラクタを利用します。

std::map<std::string, int> original = {{"A", 1}, {"B", 2}};

// originalをコピーして初期化
std::map<std::string, int> copyMap(original);

構造体やクラスのメンバ変数としてmapを初期化する

実務では、main 関数の中で単発で使うよりも、クラスや構造体のメンバとして map を持たせるケースの方が多いでしょう。

この場合、初期化の方法がいくつかあります。

クラス内でのデフォルト初期化(NSDMI)

C++11以降では、メンバ変数の宣言時に直接初期値を与えることができます(Non-static Data Member Initializers)。

これが最も直感的でおすすめの方法です。

#include <iostream>
#include <map>
#include <string>

class GameConfig {
public:
    // メンバ宣言時に初期化してしまう
    std::map<std::string, int> settings = {
        {"ResolutionX", 1920},
        {"ResolutionY", 1080},
        {"Volume", 100}
    };

    void showSettings() {
        std::cout << "Volume: " << settings["Volume"] << std::endl;
    }
};

int main() {
    GameConfig config;
    config.showSettings();
    return 0;
}

実行結果

Volume: 100

GameConfig クラスのインスタンスが生成されると同時に、settings マップも指定した値で初期化されます。

コンストラクタを書く手間が省けるため、固定の初期設定を持たせたい場合に非常に便利です。

コンストラクタ初期化子リストでの初期化

引数によって初期値を変更したい場合などは、コンストラクタのメンバ初期化子リストを使用します。

class Dictionary {
private:
    std::map<int, std::string> words;

public:
    // コンストラクタで初期化
    Dictionary() : words{{1, "One"}, {2, "Two"}} {
        // コンストラクタ本体
    }
};

キーが存在しない場合のデフォルト値(0初期化)について

std::map を使う上で非常に重要なのが、「存在しないキーにアクセスしたときの挙動」です。

特に [] 演算子(添字演算子)を使った場合、意図せず初期化が行われることがあります。

[]演算子によるアクセスと自動生成

map[key] という形式で値を取得しようとした際、もしそのキーが map の中に存在しなかった場合、C++は自動的にそのキーを生成し、値を「ゼロ初期化(デフォルト値)」して挿入します。

#include <iostream>
#include <map>
#include <string>

int main() {
    std::map<std::string, int> counts;

    // "Apple"というキーはまだ存在しない
    // しかし、参照した瞬間に生成され、intのデフォルト値(0)が入る
    std::cout << "Apple count: " << counts["Apple"] << std::endl;

    // サイズを確認すると、要素が1つ増えている
    std::cout << "Map size: " << counts.size() << std::endl;

    return 0;
}

実行結果

Apple count: 0
Map size: 1

counts["Apple"] と記述した時点で、map はキー “Apple” を検索します。
見つからなかったため、新しいエントリを作成し、値の型である int のデフォルト値 0 で初期化します。

これが std::string 型の値であれば空文字 "" に、ポインタであれば nullptr になります。

「単に値があるか確認したいだけ」のつもりが、勝手に要素が増えてしまうというバグの原因になりやすいため、存在確認には find() メソッドや count()、C++20以降なら contains() を使いましょう。

要素の追加方法と初期化との違い

初期化時以外に要素を追加する方法についても整理しておきましょう。

insertとemplaceの違い

  • insert: 作成済みのペア(std::pair)をコピー(またはムーブ)して追加します。
  • emplace: map の内部で要素を直接構築します。無駄なコピーが発生しないため、パフォーマンス面で有利です。
std::map<int, std::string> m;

// insert: pairを作って渡す
m.insert(std::make_pair(1, "Data"));

// emplace: 引数をそのまま渡して内部で構築
m.emplace(2, "Info");

[]演算子を使った追加と上書き

m[key] = value; という書き方は、キーが存在しなければ「新規追加(初期化)」、存在すれば「上書き(代入)」となります。

直感的で使いやすいですが、前述の通り「参照による自動生成」の仕様を理解して使う必要があります。

C++のスキルを活かして年収を上げる方法

以上、C++でのstd::mapの初期化方法について解説してきました。

なお、C++のスキルがある場合には、「転職して年収をアップさせる」「副業で稼ぐ」といった方法を検討するのがおすすめです。

C++を扱えるエンジニアは希少価値が高いため、転職によって数十万円の年収アップはザラで、100万円以上年収が上がることも珍しくありません。

なお、転職によって年収を上げたい場合は、エンジニア専門の転職エージェントサービスを利用するのが最適です。

今すぐ転職する気がなくとも、とりあえず転職エージェントに無料登録しておくだけで、スカウトが届いたり、思わぬ好待遇の求人情報が送られてきたりするというメリットがあります。

併せて、副業案件を獲得できるエージェントにも登録しておくと、空いている時間を活かして稼げるようなC++の案件を探しやすくなります。

転職エージェントも副業エージェントも、登録・利用は完全無料なので、どんな求人や副業案件があるのか気になる方は、気軽に利用してみるとよいでしょう。