【问题标题】:Is there a way to extract a node from std::list similar to what std::map::extract does?有没有办法从 std::list 中提取节点,类似于 std::map::extract 所做的?
【发布时间】:2020-08-07 20:39:03
【问题描述】:

对于我的任务,我使用std::list<Key> 来维护临时 LRU 缓存中元素的顺序。因此,一种常见的操作是将列表元素取出并放回列表的前面。

显然,可以先使用std::list::erase再使用std::list::push_front来实现。但是,当我想做的只是将列表节点移动到不同的位置时,我不喜欢处理内存重新分配的想法。

这正是extract 方法允许我们为std::mapstd::set 等做的事情:取出一个节点,修改它然后放回去,根本不需要重新分配。

是否有合理的解释为什么std::list 缺少相同的功能,是否有一种解决方法可以用现有的类 API 来模仿它?

【问题讨论】:

  • 我看不出有什么理由不进一步扩展这个想法,并拥有 intrusive containers ,例如在 STL 中提升 intrusive list 和 boost intrusive map,并制作非侵入式建立在侵入式之上。
  • This answer 是相关的。您可以使用单个命令 list.splice(list.begin(), list, iter) 执行此操作,其中 iter 指向您要移动到开头的元素。
  • 也可以查看生成的程序集,基本上只是重新分配了相关的指针:godbolt.org/z/eNAxpC
  • @DanielLangr 这很有趣。在我的快速研究中,拼接似乎是“从一个列表到另一个列表”。不过,它确实可以在同一个列表中工作。
  • @DanielLangr,您在下面提供的 eel.is 链接显示 splice 重载之一确实禁止从列表拼接到自身,即获取整个源列表内容的拼接。所以你只是部分不正确。

标签: c++ stl c++17 stdmap stdlist


【解决方案1】:

有一个std::list::splice 成员函数可能是您想要的。它对列表节点的内部指针进行操作。 我没有看到从/到同一个列表拼接的方法,但是你可以拼接到一个临时(空)std::list,然后拼接回原始列表的前面。

经审核,允许在同一个列表中进行拼接。将整个列表拼接到自身是未定义的。将单个元素拼接到同一个列表中是可以的,并且只要目标位置不包含在拼接的范围内,拼接一系列元素是可以的。 (谢谢你,丹尼尔·朗格)

【讨论】:

  • splice 可以,谢谢!不过确实感觉很hacky。仍然不明白是什么让标准的开发人员跳过将extract 提供给std::list
  • 我不知道。这可能是那些“如果你想要就提交提案”的事情之一。
  • 请注意,此函数具有线性复杂度。
  • @Ayxan 我认为是constant time 用于拼接单个节点。
  • 有趣。我必须将它与其他一些功能混合在一起。感谢您的参考
猜你喜欢
  • 2012-04-22
  • 1970-01-01
  • 2016-09-10
  • 2014-03-23
  • 2011-03-24
  • 1970-01-01
  • 2010-12-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多