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

2022-01-07 00:00:00 c++ c++11 stl unordered-map

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

This question might be a bit sketchy because I do not have the code available at home, but I know this thing otherwise will bug me the whole weekend.

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

When I tried to update some code to C++11 I began replacing some std::map with std::unordered_map. The code only used std::map::find() to access a specific element in the map, so I figured the replacement should be easy. The returned iterator was stored in an auto-typed variable (auto res = map.find( x ), so the typing should check out fine. However when accessing the stored element using res->second.do_stuff() I got a compiler error, telling me, that struct std::pair<char, B> does not have a member second. Now this really confused me, but unfortunately I did not have time to investigate further.

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

Maybe this is enough information, so someone can give me a hint on this weird compiler error. Or is my understanding that std::map and std::unordered_map should have the same interface except for the parts which need an ordering, not correct?

编辑:

正如这里承诺的那样,对问题进行更多分析.很可能这将使某人现在可以更好地帮助我.正如我从评论中的提示中猜测的那样,这实际上并不是由我访问地图中元素的点引起的,而是由代码的其他部分引起的.我发现的原因是,我使用 X 类中的映射来存储指向 X 类其他元素的指针(一种树结构).然而,这似乎适用于 std::map 但不适用于 std::unordered_map.下面是一些展示问题的非常简单的代码:

As promised here some more analysis on the problem. Most likely this will allow someone to help me out better now. As I guessed from the hints in the comments, this was not really caused by the point where I accessed the elements in the map, but by some other part of the code. The reason I found was, that I used the map within Class X to store pointers to other elements of Class X (a kind of tree structure). However this seems to work for std::map but not for std::unordered_map. Here is some very simple code that exhibits the problem:

#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 有效 std::unordered_map 无效.任何想法为什么会这样,或者可以做些什么来让它与 std::unordered_map 一起工作?

std::map works std::unordered_map does not work. Any Ideas why this is the case, or what can be done to get it to work with a std::unordered_map?

推荐答案

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

I guess that because std::unordered_map needs to rehash, and therefore copy elements, the types need to be complete, whereas a map, only ever working with pointers to elements, will not exhibit that problem.

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

The solution here is to have an unordered map to a pointer:

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

相关文章