ホームに戻る
出典 :
C++日本語リファレンス C++ 連想配列クラスとは std::mapまとめ - Qiita C++のmapの初期化 -技術は楽するためにある
関連 :
コンテナ イテレータ 範囲ベースfor [.NET]Dictionary(連想配列)
目次 :

連想配列とは

検索に使用するキーと、対応する値のペアを保持するコンテナのこと。
キーと値のそれぞれに任意の型を用いることができ、要素をキーにより高速に検索できる。
.NET、PythonのDictionary、Perl、Rubyのハッシュテーブルと共通の概念。
std::map はすべてのキーがユニークである必要があるが、キーの重複が許される std::multimap も存在。
また、C++11以降ではより高速でメモリ効率の良い std::unordered_map / std::unordered_multimap も使用できる。
クラス 必要なヘッダ キーの
重複
要素の
ソート
解説
std::map #include <map> 不可 昇順 標準の連想配列クラス。
要素はキーの順にソートされる。
std::multimap 要素の重複が認められる map 。
要素はキーの順にソートされる。
std::unordered_map #include <unordered_map> 不可 なし 要素がソートされない map 。
高速でメモリ効率が良い。C++11以降で使用可能。
std::unordered_multimap 要素がソートされない multimap 。
高速でメモリ効率が良い。C++11以降で使用可能。

使用例

宣言・初期化

{ キー , 値 } の順に記述。
// エラーコード対エラーメッセージ // キー : const long // 値 : const wchar_t* std::map<const long, const wchar_t*> cErrorInfo = { // キー , 値 { OPOS_E_CLOSED , _T("クローズ中") }, //< オープン未済 { OPOS_E_NOTCLAIMED , _T("Claim中ではない") }, //< Claim未済 { OPOS_E_DISABLED , _T("DeviceEnabled=TRUE中でない") }, //< DeviceEnabledオフ { OPOS_E_BUSY , _T("ビジー") }, //< ビジー { OPOS_E_NOHARDWARE , _T("ハードウェア異常(決済デバイス)") }, //< 接続異常 };

参照・更新・追加

添字演算子( [] )でキーを指定することで、キーに対応する値を取得、または更新できる。
存在しないキーを指定した場合は新しい要素(キーと値のペア)が追加される。このとき値を代入しなければ、値として指定された型の既定値が格納される。
#include <iostream> #include <map> int main() { // 空の map 作成 // キー : std::string // 値 : int std::map<std::string, int> sampleMap {}; // sampleMap["first"] を追加 sampleMap["first"] = 3; // sampleMap["second"] を追加 sampleMap["second"] = 9; // sampleMap["first"] を更新 sampleMap["first"] = 13; // sampleMap["third"] を追加 // (値を代入しない) sampleMap["third"]; std::cout << sampleMap["first"] << std::endl; std::cout << sampleMap["second"] << std::endl; std::cout << sampleMap["third"] << std::endl; }
実行結果
13 //< sampleMap["first"] 9 //< sampleMap["second"] 0 //< sampleMap["third"] : int 型の既定値

注意が必要な点

添字演算子では const な map にアクセスできない。後述の at() を用いる。

その他のメンバ関数・演算子

メンバ 解説
at()
(C++11以降)
キーを指定し、対応する値を取得する。
値の取得のみで更新は不可。const な map にアクセス可能。
insert() キーと値を指定して要素を追加する。
elase() キーを指定し、対応する要素を削除する。
size() 要素数を取得する。

使用例

// map の作成 std::map<std::string, int> m {}; // m["first"] 、m["second"] を追加 : 添字演算子 m["first"] = 15; m["second"] = 7; // m["third"] を追加 : insert() m.insert( 3, 8 ); // m の要素数を取得 : size() std::cout << m.size() << std::endl; // m["second"] を削除 : elase() m.elase( "second" ); // m の要素数を取得 : size() std::cout << m.size() << std::endl; // 各要素を取得 : at() std::cout << m.at( "first" ) << std::endl; // std::cout << m.at( "second" ) << std::endl; m["second"] は存在しないため実行時例外 std::cout << m.at( "third" ) << std::endl;
実行結果
3 // size() 初回 2 // size() 2回目 15 // m["first"] 8 // m["third"]

マップの走査(スキャン)

マップの全要素に順にアクセスする際は、以下の手順を用いる。
マップの各要素は std::pair 型として存在し、std::pair::first でキーを、std::pair::second で値を取得できる。

イテレータを用いる場合

std::map<int, int> m {}; : auto end = m.end(); for( auto it = m.begin(); m != end ; ++it ) { int key = it->first; int val = it->second; }
要素の参照のみで更新を行わないのであれば、読み取り専用イテレータを用いると安全である(C++11以降)。
但しC++11以降であれば、後述の範囲ベースforを用いたほうが簡便である。

範囲ベースforを用いる場合(C++11以降)

std::map<int, int> m {}; : for( const auto& elem : m ) { int key = elem.first; int val = elem.second; }
要素の更新を行わないのであれば、上記のように一時変数を const 化すると安全である。

マップの逆引き

通常とは逆に、値からキーを求める場合は以下のように記述する。
(ここでは範囲ベースforを用いているが、イテレータを用いることも可能である。)
std::map<int, int> m {}; : // 検索する値 int seekVal = 8; // seekVal に対応するキー int targetKey; for( const auto& elem : m ) { // seekVal が m 中に見つかった場合は targetKey にキー値を格納して抜ける if( elem.second == seekVal ) { targetKey = elem.first; break; } } // (見つからなかった場合の処理) :