我有一个使用相同键的多个值的map,键是C字符串
类型。
我期望只有一个指定键的条目。
然而,当唯一地识别一个键时,该map似乎考虑了它的地址。
#include <cassert>
#include <iostream>
#include <string>
#include <unordered_map>
typedef char const* const MyKey;
/// @brief Hash function for StatementMap keys
///
/// Delegates to std::hash<std::string>.
struct MyMapHash {
public:
size_t operator()(MyKey& key) const {
return std::hash<std::string>{}(std::string(key));
}
};
typedef std::unordered_map<MyKey, int, MyMapHash> MyMap;
int main()
{
// Build std::strings to prevent optimizations on the addresses of
// underlying C strings.
std::string key1_s = "same";
std::string key2_s = "same";
MyKey key1 = key1_s.c_str();
MyKey key2 = key2_s.c_str();
// Make sure addresses are different.
assert(key1 != key2);
// Make sure hashes are identical.
assert(MyMapHash{}(key1) == MyMapHash{}(key2));
// Insert two values with the same key.
MyMap map;
map.insert({key1, 1});
map.insert({key2, 2});
// Make sure we find them in the map.
auto it1 = map.find(key1);
auto it2 = map.find(key2);
assert(it1 != map.end());
assert(it2 != map.end());
// Get values.
int value1 = it1->second;
int value2 = it2->second;
// The first one of any of these asserts fails. Why is there not only one
// entry in the map?
assert(value1 == value2);
assert(map.size() == 1u);
}
在将这些元素插入后,调试器中的打印显示地图包含两个元素。
(gdb) p map
$4 = std::unordered_map with 2 elements = {
[0x7fffffffda20 "same"] = 2,
[0x7fffffffda00 "same"] = 1
}
为什么如果散列函数只考虑了值(在代码中被断言),委托给
std::hash<std::string>
的话,仍然会出现这种情况?此外,如果这是预期的行为,我如何使用C字符串作为键创建一个1:1的键值映射的地图?
const char*
,而不是使用string
呢?MyMapHash
的定义在哪里? - EdChumconst char*
兼容。我想避免在其上构建一个string
的开销,但我现在意识到我已经在我定义的MyMapHash
中这样做了。所以我可以使用string
。谢谢! - Andrei Pavel