持有tbb::concurrent_unordered_map元素引用是否安全?
首先可以明确地告诉你:持有tbb::concurrent_unordered_map中元素的引用是完全安全的,即使在并发插入新元素的场景下。下面具体解释原因:
从TBB文档的隐含逻辑推导
你引用的TBB文档说明:
Like std::list, insertion of new items does not invalidate any iterators, nor change the order of items already in the map. Insertion and traversal may be concurrent.
虽然文档没有直接说“元素不会移动位置”,但迭代器的有效性直接和元素的物理地址绑定:如果元素的内存位置发生了移动,那么指向该元素的迭代器必然会失效。既然文档明确插入操作不会使任何迭代器失效,这就意味着已有元素的物理地址永远不会改变——这和std::list的特性完全一致:std::list的迭代器不失效,正是因为元素存储在独立节点中,插入不会移动已有节点的位置。
对比std::unordered_map的关键差异
std::unordered_map在扩容时会一次性重新哈希所有元素,将它们移动到新的内存区域,这会导致所有迭代器和引用失效。但tbb::concurrent_unordered_map采用了渐进式扩容的实现:它不会一次性迁移所有元素,而是在后续的操作中逐步将旧哈希桶的元素迁移到新桶,且每个元素都存储在独立分配的节点中。这种设计保证了已有元素的内存地址永远不会被改变,因此指向它们的引用也不会悬空。
结合你的代码场景验证
你的代码中,MyClass持有getMyStruct返回的引用,只要对应的元素没有被从myMap中删除,这个引用就可以安全使用。而你提到这段代码已经高频运行一年且没有问题,这也从实践层面验证了安全性——如果插入操作会导致元素移动,早就会出现悬空引用引发的崩溃、内存错误等问题了。
唯一需要注意的风险
只有当对应的元素被从myMap中删除时,持有的引用才会变成悬空引用。但从你的描述来看,代码只涉及元素插入,没有删除操作,所以这个风险在你的场景下不存在。
内容的提问来源于stack exchange,提问作者Paul Beerkens

