ホームに戻る
出典 :
関連 :
目次 :
連想配列とは
検索に使用するキーと、対応する値のペアを保持するコンテナのこと。
キーと値のそれぞれに任意の型を用いることができ、要素をキーにより高速に検索できる。
.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を用いたほうが簡便である。
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;
}
}
// (見つからなかった場合の処理)
: