std::tr1::unordered_mapのキーの型をconst char*にした場合の挙動
g++(及びその他)のunordered_mapで文字列をキーにしたい場合の注意書き。
unordered_map
以下、その際の挙動の確認用のコード:
/** * ファイル名: str_map.cc * コンパイル: g++ -o str_map str_map.cc * gcc-4.6.1 */ #include <string> #include <cstring> #include <tr1/unordered_map> #include <iostream> int main() { // ハッシュマップ作成 std::tr1::unordered_map<const char*, int> cstr_map; // const char*用 std::tr1::unordered_map<std::string, int> str_map; // std::string用 // キーを用意 char key1[] = "abc"; char* key2 = new char[4]; strcpy(key2, "abc"); // キーの値とアドレスを出力 std::cout << std::endl << "--" << std::endl; std::cout << "key1: '" << key1 << "' (addr: " << (long)(key1) << ")" << std::endl; std::cout << "key2: '" << key2 << "' (addr: " << (long)(key2) << ")" << std::endl; // key1を要素挿入 cstr_map[key1] = 10; str_map[key1] = 10; // key1とkey2を検索 std::cout << std::endl << "--" << std::endl; std::cout << "cstr_map: key1=" << cstr_map[key1] << ", key2=" << cstr_map[key2] << std::endl; std::cout << " str_map: key1=" << str_map[key1] << ", key2=" << str_map[key2] << std::endl; // key1の値を変えてみる key1[1] = '2'; // key1 = "a2c" // key1を検索 std::cout << std::endl << "--" << std::endl; std::cout << "key1: '" << key1 << "' (addr: " << (long)(key1) << ")" << std::endl; std::cout << "cstr_map: key1=" << cstr_map[key1] << std::endl; std::cout << " str_map: key1=" << str_map[key1] << std::endl; return 0; }
実行結果:
-- key1: 'abc' (addr: 140736322707456) # key1とkey2は同じ文字列だけど、アドレスは異なる key2: 'abc' (addr: 30732528) -- cstr_map: key1=10, key2=0 # key1のみヒット str_map: key1=10, key2=10 # key1とkey2の両方にヒット -- key1: 'a2c' (addr: 140736035469872) cstr_map: key1=10 # ヒット(ポインタ値が同じなため) str_map: key1=0 # ヒットしない(文字列が変わっているため)
分かってみれば、これはこれで自然な動作なので特に違和感もないけど、最近はC++がご無沙汰だったためか(文字列ではなくポインタ値として扱われていることに)すぐに気づかずに少しはまってしまった。