【发布时间】:2021-05-27 05:42:58
【问题描述】:
我正在将我的 c++ 应用程序从 GCC4.7 移植到 GCC7 并遇到了一个问题,即 std::hash_map find() 函数为映射中存在的键返回 null 结果。
现有代码:
struct eqfunc {
bool operator()(const char* const &s1, const char* const &s2) const {
std::cout << "eqfunc in action " << s1 << " - " << s2 << std::endl;
return strcmp(s1,s2) == 0;
}
};
template <typename T> class customMap : public std::hash_map<const char*,T,std::hash<const char*>,eqfunc> {};
customMap<const char*> cstmMap;
std::cout << "Insert abc" << std::endl;
cstmMap["abc"] = "ABC";
std::cout << "Insert def" << std::endl;
cstmMap["def"] = "DEF";
std::cout << "Insert xyz" << std::endl;
cstmMap["xyz"] = "XYZ";
std::cout << "Find def in cstmMap" << std::endl;
string findString("def");
customMap<const char*>::iterator ptr = cstmMap.find((char *)findString.c_str());
LOG_INFO("output ptr %s", ptr);
这在 GCC4.7 平台上运行良好。当我将代码移植到 GCC7 时,我注意到 find() 会返回 null 结果的行为,即使对于地图中存在的键也是如此。
GCC7 中的示例运行输出
Insert abc
Insert def
Insert xyz
Find def in cstmMap
output ptr (null)
将std::hash_map 更新为std::unordered_map 也不起作用:
template <typename T> class customMap : public std::unordered_map<const char*,T,std::hash<const char*>,eqfunc> {};
我注意到使用std::unordered_map 的另一个奇怪行为是eqfunc 在多次运行中没有以一致的模式执行
样本 1 运行
Insert abc
Insert def
eqfunc in action def - abc
Insert xyz
Find def in cstmMap
eqfunc in action def - xyz
output ptr (null)
样本 2 运行
Insert abc
Insert def
eqfunc in action def - abc
Insert xyz
Find def in cstmMap
output ptr (null)
注意:这是非常大的代码库,将const char * 更改为std::string 并不简单,需要大量工作。
我想知道是否有任何变通方法可以使其与地图键的现有 const char * 数据类型一起使用。对此的任何帮助将不胜感激。
【问题讨论】:
-
find()永远不会返回null。请包括实际输出 -
您还需要一个自定义哈希函数。默认情况下
std::unordered_map将散列指针(而不是它们指向的)。因此,如果两个文字 c 字符串相同但保存在内存中的不同地址,则它们的哈希值不会相同。常量折叠的变化可能会产生您所看到的差异。 -
std::hash<const char*>看起来很可疑。请参阅cppreference:“C 字符串没有专门化。std::hash生成指针值(内存地址)的哈希值,它不检查任何字符数组的内容。” -
发布的代码在 gcc 4.7 中和 gcc 7 中一样损坏。
-
@karthik.zorfy 只有在哈希值相同时才使用 Equals。哈希找到桶然后等于检查桶中的每个项目。如果哈希不起作用/损坏,则等于无关紧要。
标签: c++