Unordered_map 与地图

Posted

技术标签:

【中文标题】Unordered_map 与地图【英文标题】:Unordered map vs map 【发布时间】:2020-12-06 10:13:46 【问题描述】:

有谁知道为什么Dict 类无效但Dict2 没问题?


#include <string>
#include <unordered_map>
#include <map>
#include <variant>

class Dict

public:
    Dict() 

private:
    std::unordered_map<std::string, std::variant<Dict, std::string>> data;
;

class Dict2

public:
    Dict2() 

private:
    std::map<std::string, std::variant<Dict2, std::string>> data;
;

int main()

    Dict d;
    Dict2 d2;
    return 0;

我得到一个错误

‘value’ is not a member of ‘std::is_trivially_move_constructible&lt;Dict&gt;’.

我查找了普通移动和复制构造的概念,据我所知,应该定义或删除移动构造函数。 我猜这是因为使用std::unordered_mapstd::variant 并且编译器不知道应该如何移动对象。但我不确定我是否理解正确。

【问题讨论】:

【参考方案1】:

我相信这两种情况下的行为都是未定义的。 Dict2 只是偶然执行编译; “似乎有效”是未定义行为的一种可能表现形式。

[res.on.functions]/1 在某些情况下(替换函数、处理函数、对用于实例化标准库模板组件的类型的操作),C++ 标准库依赖于由一个 C++ 程序。如果这些组件不符合其要求,则本国际标准不要求 实施。

[res.on.functions]/2 特别是,在以下情况下效果未定义: ... (2.5) — 如果在实例化模板组件时将不完整类型 (6.9) 用作模板参数,除非该组件特别允许。

DictDict2 是不完整的类型,直到它们的定义的右大括号。 std::variant 不允许使用不完整的类型进行实例化。

【讨论】:

感谢您的回答。那么如何建议解决这个问题呢?我还使用std::map 进行了进一步测试,它的行为符合我的预期。我可以创建一个指向std::stringkey1 和一个指向模仿链表行为的同一类的对象的key2。但是我不能用std::unordered_map 来做这件事,因为它不能编译。 好吧,作为一种快速解决方法,您可以在堆上分配嵌套的Dict,如std::variant&lt;std::unique_ptr&lt;Dict&gt;, std::string&gt;std::unique_ptr 明确允许不完整类型作为参数。

以上是关于Unordered_map 与地图的主要内容,如果未能解决你的问题,请参考以下文章

遍历unordered_map cpp的问题

unordered_map 哈希函数 / 如何防止 unordered_map 被卡

std::unordered_map 非常高的内存使用率

c++ unordered_map 碰撞处理,调整大小和重新散列

C++源码剖析——unordered_map和unordered_set

为啥 unordered_map 需要散列而不是地图?