【问题标题】:splice() on std::list and iterator invalidationstd::list 上的 splice() 和迭代器失效
【发布时间】:2010-09-13 16:15:03
【问题描述】:

list::splice() 的 3 参数形式将单个元素从一个列表移动到另一个列表。 SGI's documentation 明确声明所有迭代器,包括指向被移动元素的迭代器仍然有效。 Roguewave's documentation 没有说明 splice() 方法的迭代器失效属性,而 C++ 标准明确声明它使所有迭代器和对被拼接元素的引用失效。

splicing() 在实践中按照 SGI 的定义工作,但在微软 STL 实现的调试/安全 SCL 版本(严格遵循标准的字母)中出现断言失败(取消引用无效迭代器)。

现在,我使用 list 正是因为我想在列表之间移动一个元素,同时保持指向它的迭代器的有效性。该标准对原始 SGI 规范做出了极其无益的更改。

我该如何解决这个问题?或者我应该务实一点,把头埋在沙子里(因为拼接确实不会在实践中使迭代器失效——即使在 MS 的实现中,一旦迭代器调试被关闭)。

【问题讨论】:

  • 好问题。最后一句话是什么?
  • 标准是愚蠢的,但是正确的。不要在符合标准的程序中使用拼接。也许 C++1x 修正了这种情况;我没有检查。
  • 我刚查了一下,确实有变化。保留的措辞是 LWG 缺陷 250 之一:旧迭代器是有效的,并且表现得好像它们指向新容器一样。

标签: c++ list containers iterator


【解决方案1】:

我有一个列表数组(元素的等价类),我正在使用 splice 在列表之间移动元素。我有一个额外的迭代器数组,它使我可以直接访问任何列表中的任何元素并将其移动到另一个列表。不会同时搜索和修改任何列表。我可以在拼接后重新初始化元素迭代器,但这有点难看..我想我暂时会这样做。

【讨论】:

    【解决方案2】:

    问题在于,如果迭代器仍然指向被移动的元素,那么之前与“移动”迭代器关联的“结束”迭代器已经改变。除非您编写一些复杂的循环,否则这实际上是一件坏事——尤其是因为其他开发人员更难以理解。

    我认为更好的方法是使用指向移动迭代器前后元素的迭代器。

    【讨论】:

    • 取决于他是否保留迭代器以访问元素而不会失去列表操作能力,或者他当前是否正在迭代列表,在这种情况下他确实必须小心。
    【解决方案3】:

    好的,根据thisthis 链接,这似乎是标准中的一个缺陷。似乎“把头埋在沙子里”是个好策略,因为它会在新的库版本中得到修复。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-14
      • 2012-12-05
      • 1970-01-01
      • 2020-11-22
      • 2018-04-07
      相关资源
      最近更新 更多