什么可以使 std::map 找不到其中一个键?
What can bring a std::map to not find one of its keys?
我有一个 std::map 将 const char*
键与 int
值关联:
std::map<const char*, int> myMap;
我用三个键初始化它,然后检查它是否能找到它:
myMap["zero"] = 0;
myMap["first"] = 1;
myMap["second"] = 2;
if (myMap.at("zero") != 0)
{
std::cerr << "We have a problem here..." << std::endl;
}
没有打印任何内容。从这里看,一切正常。
但后来在我的代码中,在不对这张地图做任何改动的情况下,我再次尝试找到一个密钥:
int value = myMap.at("zero");
但是at
函数抛出一个std::out_of_range
异常,这意味着它找不到元素。 myMap.find("zero")
认为相同,因为它 returns 是地图末尾的迭代器。
但最令人毛骨悚然的部分是关键确实在地图中,如果就在调用 at
函数之前,我像这样打印地图的内容:
for (auto it = myMap.begin(); it != myMap.end(); it++)
{
std::cout << (*it).first << std::endl;
}
输出符合预期:
zero
first
second
这怎么可能?我不使用任何 beta 测试库或任何应该不稳定的东西。
你有一个字符指针映射,而不是字符串。地图查找基于指针值(地址)而不是所指向的值。在第一种情况下,在映射中找到 "zero" 的地方,您的编译器已经执行了一些字符串合并,并且正在为两个相同的字符串使用一个字符数组。这不是语言所要求的,而是一种常见的优化。在第二种情况下,当没有找到字符串时,这个合并还没有完成(可能你这里的代码在不同的源模块中),所以映射中使用的地址与插入的地址不同,然后找不到.
要解决此问题,请在地图中存储 std::string 个对象,或者在地图声明中指定比较以根据字符串而不是地址进行排序。
映射的关键是 char *
。所以 map 比较函数将尝试比较原始指针值而不是 c 风格的 char 字符串等价性检查。所以声明以 std::string
为键的地图。
如果您不想处理 std::string
并且仍然想要具有改进的时间复杂度的相同功能,复杂的数据结构是 trie。查看一些实现,例如 Judy Array.
我有一个 std::map 将 const char*
键与 int
值关联:
std::map<const char*, int> myMap;
我用三个键初始化它,然后检查它是否能找到它:
myMap["zero"] = 0;
myMap["first"] = 1;
myMap["second"] = 2;
if (myMap.at("zero") != 0)
{
std::cerr << "We have a problem here..." << std::endl;
}
没有打印任何内容。从这里看,一切正常。
但后来在我的代码中,在不对这张地图做任何改动的情况下,我再次尝试找到一个密钥:
int value = myMap.at("zero");
但是at
函数抛出一个std::out_of_range
异常,这意味着它找不到元素。 myMap.find("zero")
认为相同,因为它 returns 是地图末尾的迭代器。
但最令人毛骨悚然的部分是关键确实在地图中,如果就在调用 at
函数之前,我像这样打印地图的内容:
for (auto it = myMap.begin(); it != myMap.end(); it++)
{
std::cout << (*it).first << std::endl;
}
输出符合预期:
zero
first
second
这怎么可能?我不使用任何 beta 测试库或任何应该不稳定的东西。
你有一个字符指针映射,而不是字符串。地图查找基于指针值(地址)而不是所指向的值。在第一种情况下,在映射中找到 "zero" 的地方,您的编译器已经执行了一些字符串合并,并且正在为两个相同的字符串使用一个字符数组。这不是语言所要求的,而是一种常见的优化。在第二种情况下,当没有找到字符串时,这个合并还没有完成(可能你这里的代码在不同的源模块中),所以映射中使用的地址与插入的地址不同,然后找不到.
要解决此问题,请在地图中存储 std::string 个对象,或者在地图声明中指定比较以根据字符串而不是地址进行排序。
映射的关键是 char *
。所以 map 比较函数将尝试比较原始指针值而不是 c 风格的 char 字符串等价性检查。所以声明以 std::string
为键的地图。
如果您不想处理 std::string
并且仍然想要具有改进的时间复杂度的相同功能,复杂的数据结构是 trie。查看一些实现,例如 Judy Array.