为什么我不能将 std::map 替换为 std::unordered_map

Why can't I replace std::map with std::unordered_map

本文关键字:std map unordered 替换 为什么 不能      更新时间:2023-10-16

这个问题可能有点粗略,因为我家里没有可用的代码,但我知道这件事会困扰我整个周末。

当我尝试将一些代码更新到c++ 11时,我开始用std::unordered_map替换一些std::map。代码只使用std::map::find()来访问地图中的特定元素,所以我认为替换应该很容易。返回的迭代器存储在auto类型的变量(auto res = map.find( x ))中,因此类型应该检查得很好。然而,当使用res->second.do_stuff()访问存储的元素时,我得到了一个编译器错误,告诉我,struct std::pair<char, B> does not have a member second。现在我真的很困惑,但不幸的是,我没有时间进一步调查。

也许这是足够的信息,所以有人可以给我提示这个奇怪的编译错误。还是我的理解是std::mapstd::unordered_map除了需要排序的部分应该是一样的接口,不正确?

编辑:

如前所述,这里对问题进行了更多的分析。这很可能会让别人更好地帮助我。正如我从注释中的提示中猜测的那样,这实际上不是由我访问映射中的元素的点引起的,而是由代码的其他部分引起的。我发现原因是,我使用类X中的映射来存储指向类X的其他元素的指针(一种树结构)。然而,这似乎适用于std::map,但不适用于std::unordered_map。下面是显示这个问题的一些非常简单的代码:

#include <stdint.h>
#include <unordered_map>
#include <map>
class Test {
  std::map<uint32_t, Test> m_map1; // Works
  std::unordered_map<uint32_t, Test> m_map; // gives error: ‘std::pair<_T1, _T2>::second’ has incomplete type
};
int main() {
  return 1;
}

std::map works std::unordered_map not work。

是否知道为什么会这样,或者可以做些什么来让它与std::unordered_map一起工作?

我猜,因为std::unordered_map需要重新散列,因此需要复制元素,所以类型需要是完整的,而map只使用指向元素的指针,不会出现这个问题。

这里的解决方案是使用一个指向指针的无序映射:

std::unordered_map<uint32_t, std::shared_ptr<Test> >. 

使用不完全类型的mapunordered_map涉及未定义行为:

在以下情况下,效果是未定义的:

[…]

-如果在实例化模板组件时使用不完整类型(3.9)作为模板参数,除非该组件特别允许。