【问题标题】:Why doesn't std::set<K, C, A>::erase take a const_iterator?为什么 std::set<K, C, A>::erase 不采用 const_iterator?
【发布时间】:2011-07-13 19:52:40
【问题描述】:

看来,根据 ISO 14882 2003(又名 C++ 的神圣标准)std::set&lt;K, C, A&gt;::eraseiterator 作为参数(不是 const_iterator

从 23.3.3 [2]

void erase(iterator position);

还可能值得注意的是,在我的 VS2008 附带的 STL 实现中,erase 需要一个const_iterator,当我尝试使用另一个编译器编译我的代码时,这导致了一个令人不快的惊喜。现在,由于我的版本采用const_iterator,因此可以使用const_iterator 实现擦除(好像它不是不言自明的)。

我想标准委员会已经考虑了一些实施(或手头现有的实施),这需要擦除以获取iterator

  • 如果您同意这种情况,您能否描述set::erase 的实现,该实现需要修改将要删除的元素(我不能)。
  • 如果您不同意,请告诉我他们到底为什么会做出这个决定?我的意思是,擦除元素只是重新排列指针!李>

编辑

我突然想到,即使在迭代器的情况下,您也无法修改集合中的元素。但问题仍然存在 - 为什么不是 const_iterator,尤其是如果它们在某种意义上是等价的

【问题讨论】:

  • 您可能会争辩说,删除一个元素会改变元素本身(它会被删除)。我认为新的 C++0x 允许擦除常量迭代器。其他容器的情况如何?
  • @Kerrel:deleted 那就是它的析构函数被调用了。并且可以在 const 对象上调用析构函数(幸运的是:))
  • set::erase 记录 iterator,而不是 const_iterator
  • GCC 4.6.1 实现了erase(const_iterator)。 3242 还规定了 const-iterator。
  • @Mat:这很有趣,因为我什至在 VS2008 附带的 STL 中打开了 &lt;set&gt; 并擦除了 const_iterator :)

标签: c++ stl set design-rationale


【解决方案1】:

这是一个缺陷。从 C++11 开始,set&lt;K,C,A&gt;::erase 采用 const_iterator

iterator erase(const_iterator position);

This 2007 年的论文说明了该错误并展示了避免该错误的实现。我不确定这篇论文是否是改变标准的原因,但这可能是一个很好的猜测。

【讨论】:

  • 非常感谢。这是一篇很棒的论文,解释得很透彻。
  • 他说它已在 N3242 中修复,但没有在论文中说明问题的基本原理和可能的替代方案……是吗?
  • @armen-tsirunyan:没有。我只想称赞他速度更快。
  • 是的,显然是这篇论文和选项 B。
【解决方案2】:

真的想不出任何理由需要iterator,所以我倾向于任意:任何修改结构的操作都需要iterator用户知道以前与 iterator 一起工作的东西以后可能不会:

  • erase 使迭代器无效。
  • insert(iter, val) 更改下一个值。

【讨论】:

  • 是的,这就是为什么 erase 不是 const 函数的原因,因为它修改了 set。但它不能也不能修改*it...我不明白你的意思,对不起。你在说什么一致性?与什么一致?
  • 我不应该使用这个词,对不起。疲劳的。我只想说,虽然erase 修改了set,但它也修改了特定iterator 的行为。相信有人最初将其设为 iterator 表示这一点并不算太远,尽管它没有真正的目的。
  • 似乎有点牵强,因为const_iteratoriterator 具有完全相同的无效规则。但是,谁知道呢? :)
【解决方案3】:

我唯一的猜测是因为 insertupper_boundlower_boundfind 正在返回迭代器(不是 const 迭代器)。我没有看到其他解释。

【讨论】:

  • 一个迭代器可以简单地转换为一个 const_iterator,所以我不认为这是一个障碍。
  • @Mark 好吧,其他解释可能是:需求中的错误。
  • @VJo:“需求中的错误”很可能是一种解释,但您关于插入、查找等的理论就是不能
  • 从接受的答案中链接的论文来看,这个理论是正确的。这不是一个合理的解释,但谁说标准委员会是合理的?
  • @Mark @Armen 确实可以将迭代器简单地转换为 const_iterator,但仍需要转换,并且 STL 被设计为尽可能优化(例如,有使用vector::operator[]时没有边界检查)
猜你喜欢
  • 1970-01-01
  • 2023-03-26
  • 2017-05-06
  • 2014-08-07
  • 2016-12-10
  • 1970-01-01
  • 1970-01-01
  • 2016-04-26
相关资源
最近更新 更多