C++ 何时使用std::无序映射::放置提示?

C++ 何时使用std::无序映射::放置提示?,c++,c++11,stl,unordered-map,C++,C++11,Stl,Unordered Map,我知道如何使用std::unordered\u map::emplace,但如何使用emplace\u hint?也没有提供一组示例来说明我们如何知道将元素放置在何处 任何人都可以提供一些关于这方面的信息,或者给出一些示例/说明,说明我们何时可能知道安放的元素应该去哪里?一个无序的地图可能会对提示做什么?好的,如果迭代器使用与被要求插入的元素相同的键来寻址元素,那么它可能很快就会失败-只是一个键比较,而不需要在该存储桶中对任何哈希冲突元素列表进行任何哈希或摸索。但是如果键不匹配,那么提示在其他方

我知道如何使用
std::unordered\u map::emplace
,但如何使用
emplace\u hint
?也没有提供一组示例来说明我们如何知道将元素放置在何处


任何人都可以提供一些关于这方面的信息,或者给出一些示例/说明,说明我们何时可能知道安放的元素应该去哪里?

一个无序的地图可能会对提示做什么?好的,如果迭代器使用与被要求插入的元素相同的键来寻址元素,那么它可能很快就会失败-只是一个键比较,而不需要在该存储桶中对任何哈希冲突元素列表进行任何哈希或摸索。但是如果键不匹配,那么提示在其他方面是无用的,因为任何其他键-无论值有多“接近”-都应该(可能)位于完全不相关的bucket(给定通常被认为是“好”的哈希函数),因此,在一个关键的比较上浪费了时间,只需要重新开始,就好像这是一个正常的
位置一样

当您插入按键元素预先排序的元素时,这可能很有用,目的是在过程中删除大量重复项,但是键太大了,因此在刚插入的元素上保留迭代器比保留键的副本更容易,或者哈希函数特别慢

unordered_-map::emplace_-hint
的另一个好处是与
map::emplace_-hint
的API兼容性更好,因此代码可以切换容器类型,并使
emplace_-hint
s不会中断编译,尽管它们可能会比切换到
emplace()时慢
因为对于
无序的
地图,帮助绘制
地图的关闭但不同的关键提示可能无效


只需获取GCC10.2
g++-E
输出,看看它是否实现了上述功能
emplace\u hint
向下调用
\u M\u insert\u multi\u节点(…)
其中有一行:

__node_base* __prev = __builtin_expect(__hint != nullptr, false)
                      && this->_M_equals(__k, __code, __hint)
                      ? __hint
                      : _M_find_before_node(__bkt, __k, __code);
上面,
\uuu k
是可以插入的键,
\uu code
是散列码,
\uu hint
是提示迭代器/指针<代码>\u M_等于(…)
返回:

return _Equal_hash_code<__node_type>::_S_equals(__c, *__n) &&
       _M_eq()(__k, this->_M_extract()(__n->_M_v()));
return\u Equal\u hash\u code::\u S\u equals(\u c,*\u n)&&
_M_eq()(u k,this->_M_extract()(u n->_M_v());
因此,在使用提示迭代器之前,它要检查哈希代码是否相等(如果已经计算了哈希,则进行快速脏检查)以及键是否相等(对于长字符串的高质量哈希,这可能是一种较慢的操作)。这是它使用提示的唯一情况。假设bucket逻辑上有一些碰撞元素与键K1、K2、K3、K4链接在一起,提示迭代器是到K4的,但您正试图用K2插入一个副本:由于迭代器只是向前的,您必须使用
\u mu find_before_node(…)
在链接中到达碰撞元素的时间早于提示指向的时间。在
\u M\u find\u before\u节点(…)
之后,您可以从K1向前扫描,以查看插入键-K2-是否已经存在于在桶上发生碰撞的元素中


(当已知密钥比较便宜时,可以通过跳过散列比较来改进实现,但使用类型特征正确处理该条件会有点困难-您如何知道哪些密钥相等函数便宜?对于小型、标准布局、可复制的类型或类似类型,可以这样假设,至少当无序容器是用默认的
std::equals
comparison…)实例化的。

我没有完全得到这个答案。可能是因为它的措辞。所以它没有用,除非我预先安排了多个键。@Dean:你不必有“预先安排的多个键”-这可能是因为它们自然出现的顺序意味着重复的键有足够高的连续出现的概率,使得围绕迭代器保留到最后放置的值是值得的,因为您可以很快拒绝重复。尽管如此,这都是基于我能想到的唯一可能使用的提示-如果您的implementation实际上没有使用提示,这是在浪费时间和精力提供提示。如果有一个函数可以向元素返回迭代器(如果找到)或有效提示(如果找不到),那么它可能会很有用-类似于您如何使用
下限
搜索或生成
映射
@user253751的提示:已经有了,并且在尝试查找后会立即插入或更新,但是是的-有时,有一些东西可以帮助您及时将两者分开:最有用的是为了保持bucket编号不变,并使用它来避免散列;您不能让迭代器指向特定的bucket&有些bucket缺少元素-因此迭代器提示很难使用。我想知道当从排序的源(如文件)填充
无序的\u映射时,是否需要整数键。我认为
emp没有任何优势如果是那样的话,我希望我错了。