无序集,值得在插入之前调用find

unordered set, it it worth calling find before insert?

本文关键字:调用 find 插入 值得 无序      更新时间:2023-10-16

当将元素插入std::unorder_set时,是否值得在std::unrdered_set::insert之前调用std::uncrdered_sep::find?根据我的理解,我应该总是调用insert,因为它返回一个std::pair,其中包含一个bool,它告诉插入是否成功。

insert之前调用find本质上是一种反模式,这通常在设计不佳的自定义集实现中观察到。也就是说,在不告诉调用者插入是否真的发生的实现中,这可能是必要的。std::set确实为您提供了这些信息,这意味着在插入舞蹈之前,通常不需要执行此查找。

insert的典型实现通常包含find的完整实现,这意味着插入前查找方法无意义地执行两次搜索。

然而,std::set设计的一些其他缺点有时确实需要在插入序列之前进行查找。例如,如果您的集合元素包含一些字段,则在实际插入发生时(仅当)需要修改这些字段。例如,您可能必须为某些指针字段分配"永久"内存,而不是这些字段在插入之前指向的"临时"(本地)内存。不幸的是,在插入之后不可能执行操作,因为std::set只为您提供对其元素的非修改访问权限。一种解决方法是先执行find,从而"预测"是否会发生实际插入,然后在执行insert之前相应地设置新元素(如为所有字段分配"永久"内存)。从性能的角度来看,这是丑陋的,但在非性能关键代码中是可以接受的。标准容器就是这样。

最好只是尝试插入,否则对哈希桶中发生冲突的任何元素进行哈希和迭代的工作都会不必要地重复。

如果您将其设置为线程安全并同时访问,那么首先调用find的作用很小,因为insert是原子的,但随后的检查会受到竞争条件的影响。

因此,一般来说,尤其是在多线程上下文中,只需插入即可。