std::unordered_map::extract 引用/指针失效
Posted
技术标签:
【中文标题】std::unordered_map::extract 引用/指针失效【英文标题】:std::unordered_map::extract references/pointers invalidation 【发布时间】:2018-10-10 11:24:55 【问题描述】:对于新的 C++17 std::unordered_map::extract
函数,文档说:
提取节点只会使提取的迭代器无效 元素,并保留非元素的相对顺序 抹去。指向提取元素的指针和引用仍然有效, 但不能在元素由节点句柄拥有时使用:它们 如果元素被插入到容器中,则变得可用。
当然,extract
使提取的迭代器无效(这是容器的东西,元素已从中删除)。但是文档对引用和指针很奇怪——它说这些仍然有效,但在重新插入(可能是另一个)容器之前不能使用——在这种情况下它们将保留它们的值(?)。
问题:我的用例是在提取后检查一个元素,即只使用一次哈希查找进行擦除-检查-丢弃操作。 extract
函数似乎非常适合这个,但是文档表明我不能使用 node_type
来检查元素。我的理解正确吗?
【问题讨论】:
【参考方案1】:是的,这就是文字所说的。
乍一看,这似乎是一个相当武断的限制,但我敢肯定它有一些好的,如果是神秘的,原因。
话虽如此,句柄本身具有成员函数value()
/key()
/mapped()
,可能对您有价值(!)。
节点句柄是一个只移动类型,它拥有并提供对存储在节点中的元素(value_type)的访问,并提供对元素的键部分(key_type)和映射部分的非常量访问元素(映射类型)。 (ref)
【讨论】:
句柄本身有成员函数 是的,我决定使用node_type::value()
,但我被文档弄糊涂了。我 am 持有指向地图中value_type
s 的指针,据推测我不应该在节点分离时取消引用。现在,当节点仍然连接时,这样的指针要么等于&nodeHandle.value()
,要么不等于......如果你明白我的意思。
简而言之 - 当地图元素被删除时,我需要从其他数据结构中清除一些指向 map::value_type
的指针。我认为通过extract
-ing 该节点并在这些结构中寻找&nodeHandle.value()
这样做是安全的。
@haelix 哦,哎哟,只要“可用”是我认为的意思,那应该可以工作
@haelix 幕后有一些手脚将pair<const Key, Value>
变成pair<Key, Value>
(没有移动或复制)。由实现来确保它有效,但不能保证这种魔法是可移植的。当类型双关出现时,语言律师会变得相当兴奋。有编译器优化要担心,缓存失效要担心,我不记得还有什么。只要您在比较指针,而不是取消引用缓存的指针,我认为您就在界限之内。
是的,那个。实际位置不太可能改变(为什么会变回来?)但是涉及的复杂性来自 C++ 不是裸机编程语言,而是具有复杂类型系统的抽象和等等等等。有人可能会争辩说,这本身就是一个巨大的抽象泄漏,但是当库在“用户空间”中实现潜在的语言功能时,就会发生这种情况。至少我们得到了我猜想的功能。【参考方案2】:
你可以认为extract
(和对应的insert
)“神奇地”改变了受影响的地图元素的类型:当元素为地图所有时,它的类型为std::pair<const key_type, mapped_type>
,但当元素为由节点句柄拥有,它的类型为std::pair<key_type, mapped_type>
(因此您可以更改键的值)。
因此,如果您在该元素归地图所有时获取该元素的引用/指针,则在提取该元素之后重新插入该元素之前,您不能使用该引用/指针,否则您将违反严格的别名规则。
但是,使用提取后获取的引用/指针是完全可以的。
【讨论】:
那是很好的洞察力,谢谢...如果直接持有指向value_type
的指针,您是否表示适用? (不是pair<>
)。以上是关于std::unordered_map::extract 引用/指针失效的主要内容,如果未能解决你的问题,请参考以下文章