当我想确保我想要使用的条目存在时,我通常会这样做。
#include <unordered_map>
struct type { int member; };
std::unordered_map<type> map;
if (map.find(key) != map.end())
map[key].member = 42;
但是,我认为它在哈希映射中对key
执行两次查找。这会缓存查找。
#include <unordered_map>
struct type { int member; };
std::unordered_map<type> map;
auto find = map.find(key);
if (find != map.end())
find->second.member = 42;
第一种选择感觉更具表现力。真的慢了吗?
答案 0 :(得分:22)
它可能会变慢,但可能不会(你现在正在进行额外的写入&#34;加速&#34;)但是当编写代码。写清楚的表达代码。然后,如果您的程序确实太慢,请在其上运行分析工具并找到您的瓶颈。如果此代码 实际上是真正的问题,那么只有尝试你的&#34;加速&#34;看看是否重要。
答案 1 :(得分:15)
是的,因为您搜索了两次密钥:map[key]
搜索与map.find
完全相同的密钥,并将结果丢弃。
就像打开一个抽屉看看是否有一个给定的物体,说“啊是的!”并关闭抽屉,然后再打开它并研究对象以改变它。
第二个代码打开抽屉,搜索一个对象并进行更改。
可以使用编译器优化来避免双重搜索,或者可以在恒定时间内减少搜索,并且可以进行编译器优化以避免将auto find
变量存储在内存中(它可以是CPU寄存器,因为它的使用非常本地化。)
整个问题实际上会减少两次哈希计算两次的时间(并且在哈希冲突的情况下遍历最终的映射槽)以及访问额外变量的时间:
2*H < H+M
这意味着H < M
。如果M是一个寄存器且H不是微不足道的,那么H
很难小于M
。
答案 2 :(得分:8)
是的,它可能会更慢但可能可测量更慢。还有一些额外的工作:
总结如果:
然后你可能会看到差异。
最后一句话 - 它可能不重要,它不是很大的架构差异,而是5s优化。因此,当分析器显示此功能导致速度减慢时,请编写更容易维护的内容并重新查看问题。
答案 3 :(得分:2)
除非您有特定原因要保留现有条目中的值(如果已存在),否则您可以完全跳过第一个搜索,只需设置新值:
#include <unordered_map>
struct type { int member; };
std::unordered_map<key_t, type> map;
map[key].member = 42;
这将修改现有条目(如果有)并插入新条目(如果不存在)。
答案 4 :(得分:2)
是的,它可能会更慢。如果你正在寻找更具表现力的东西,也许你应该封装std:unordered_map
(无论如何这可能是一个好主意)并暴露一个指针。然后你可以这样写:
auto thing = getThing(key);
if (thing)
thing->member = 42;