std::map 插入还是 std::map 查找?
假设您想要保留现有条目的地图。 20% 的情况下,您插入的条目是新数据。 使用返回的迭代器执行 std::map::find 然后 std::map::insert 是否有优势? 或者尝试插入然后根据迭代器是否指示记录已插入或未插入来采取行动是否更快?
Assuming a map where you want to preserve existing entries. 20% of the time, the entry you are inserting is new data. Is there an advantage to doing std::map::find then std::map::insert using that returned iterator? Or is it quicker to attempt the insert and then act based on whether or not the iterator indicates the record was or was not inserted?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
关于效率的任何答案都取决于 STL 的具体实现。 唯一确定的方法是对这两种方式进行基准测试。 我猜差异不太可能很大,所以根据您喜欢的风格来决定。
Any answers about efficiency will depend on the exact implementation of your STL. The only way to know for sure is to benchmark it both ways. I'd guess that the difference is unlikely to be significant, so decide based on the style you prefer.
map[ key ] - 让 stl 来解决它。 这是最有效地传达您的意图。
是的,很公平。
如果你先查找然后插入,那么当你错过时,你将执行 2 x O(log N),因为查找只会让你知道是否需要插入,而不是插入应该去的地方(lower_bound 可能会帮助你) 。 我的做法就是直接插入然后检查结果。
map[ key ] - let stl sort it out. That's communicating your intention most effectively.
Yeah, fair enough.
If you do a find and then an insert you're performing 2 x O(log N) when you get a miss as the find only lets you know if you need to insert not where the insert should go (lower_bound might help you there). Just a straight insert and then examining the result is the way that I'd go.
我似乎没有足够的点来发表评论,但勾选的答案对我来说似乎很冗长 - 当你认为 insert 无论如何都会返回迭代器时,为什么要搜索 lower_bound ,当你可以只使用返回的迭代器时。 奇怪的。
I don't seem to have enough points to leave a comment, but the ticked answer seems to be long winded to me - when you consider that insert returns the iterator anyway, why go searching lower_bound, when you can just use the iterator returned. Strange.
我认为如果您先查找然后插入,额外的成本将是当您找不到密钥并在之后执行插入时。 这有点像按字母顺序翻阅书籍,但找不到该书,然后再次翻阅书籍以了解将其插入的位置。 这归结为您将如何处理按键以及它们是否不断变化。 现在有一些灵活性,如果你没有找到它,你可以记录,异常,做任何你想做的事......
I would think if you do a find then insert, the extra cost would be when you don't find the key and performing the insert after. It's sort of like looking through books in alphabetical order and not finding the book, then looking through the books again to see where to insert it. It boils down to how you will be handling the keys and if they are constantly changing. Now there is some flexibility in that if you don't find it, you can log, exception, do whatever you want...
如果您关心效率,您可能需要查看 hash_map。
通常,地图<> 被实现为二叉树。 根据您的需要,hash_map 可能更有效。
If you are concerned about efficiency, you may want to check out hash_map<>.
Typically map<> is implemented as a binary tree. Depending on your needs, a hash_map may be more efficient.
两者之间的速度几乎没有任何差异,find 将返回一个迭代器,insert 执行相同的操作,并且无论如何都会搜索映射以确定条目是否已存在。
所以..这取决于个人喜好。 我总是尝试插入,然后在必要时更新,但有些人不喜欢处理返回的对。
There will be barely any difference in speed between the 2, find will return an iterator, insert does the same and will search the map anyway to determine if the entry already exists.
So.. its down to personal preference. I always try insert and then update if necessary, but some people don't like handling the pair that is returned.
答案是你两者都不做。 相反,您想要执行 Effective STL 的第 24 项建议的操作 斯科特·迈耶斯:
The answer is you do neither. Instead you want to do something suggested by Item 24 of Effective STL by Scott Meyers:
这个问题的答案还取决于创建要存储在映射中的值类型的成本有多大:
对于诸如 int 之类的值类型,上面的方法比查找后跟插入更有效(在没有情况下)编译器优化)。 如上所述,这是因为通过地图的搜索仅发生一次。
但是,对 insert 的调用要求您已经构造了新的“值”:
为了调用“插入”,我们正在为构造我们的值类型的昂贵调用付费 - 从您在问题中所说的来看,您不会20% 的时间使用这个新值。 在上述情况下,如果无法更改映射值类型,那么首先执行“查找”来检查是否需要构造元素会更有效。
或者,可以更改映射的值类型,以使用您最喜欢的智能指针类型存储数据的句柄。 对 insert 的调用使用空指针(构造起来非常便宜),并且仅在必要时才构造新的数据类型。
The answer to this question also depends on how expensive it is to create the value type you're storing in the map:
For a value type such as an int, the above will more efficient than a find followed by an insert (in the absence of compiler optimizations). As stated above, this is because the search through the map only takes place once.
However, the call to insert requires that you already have the new "value" constructed:
In order to call 'insert' we are paying for the expensive call to construct our value type - and from what you said in the question you won't use this new value 20% of the time. In the above case, if changing the map value type is not an option then it is more efficient to first perform the 'find' to check if we need to construct the element.
Alternatively, the value type of the map can be changed to store handles to the data using your favourite smart pointer type. The call to insert uses a null pointer (very cheap to construct) and only if necessary is the new data type constructed.