【问题标题】:Is remove_if predicate guaranteed to be called only once per iterator?是否保证每个迭代器只调用一次 remove_if 谓词?
【发布时间】:2012-07-20 03:23:38
【问题描述】:

我一直在阅读最新的 C++ 规范,但我无法确定是否可以为同一元素多次调用 remove_if。特别是,我正在查看 std::remove_ifdeque 迭代器上被调用。据我所知,如果它所做的只是从第一个参数开始并一直迭代到第二个,则没有理由多次调用它。

我正在处理的代码使用手动引用计数,因此,如果 remove_if 谓词返回 true,它将递减并删除底层对象引用。明显的问题是,这仅在 remove_if 谓词只为每个元素调用一次时才有效,否则后续调用将访问已删除的对象。有些事情告诉我,这并不能保证没问题,并且会出现相同的元素将被传递给 remove_if 谓词两次,用于单个 remove_if 调用。

如果您有某种实现迭代器的疯狂数据结构,并且说,为每个迭代器增量随机选择一个条目,直到它(随机)到达结束迭代器,我可以看到这将如何失败。但是对于像dequevectorlist 这样的直接标准化结构,单个元素可以多次传递给谓词吗?

【问题讨论】:

  • 不是您所问问题的答案,而是您的问题:§25.1[algorithms.general]/8 -- "... 函数对象 pred 不应通过以下方式应用任何非常量函数取消引用的迭代器。”
  • 请注意,remove(_if) 不会杀死元素,它只会将元素从末尾移动到它们的位置。之后您必须使用擦除删除习惯用法erase 他们:cont.erase(std::remove_if(...), cont.end());,这就是它的工作原理。如果你真的需要你的谓词来修改引用计数器,那么你就做错了,并且没有遵守RAII principle
  • @Xeo 是的。处理某人代码中的一些奇怪限制,基本上我所拥有的只是作为回调提供给库的谓词。本杰明的回答让我怀疑这种方法。
  • 由于通知而再次看到这个,我认为非常量函数的限制不是问题。例如,减少引用计数绝对是一个“恒定”的复杂性,甚至调用 free/delete 也可能是,这取决于实现。我必须说,这是一个奇怪的约束。用户代码通常没有复杂性限制。

标签: c++ stl iterator deque remove-if


【解决方案1】:

根据a draft of the standard §23.3.4.6/14:

复杂性:精确距离(开始(),结束())应用程序 的相应谓词。

如果引用有点不对,请见谅;这实际上是我第一次正式引用它。我希望这是您正在寻找的信息。

【讨论】:

  • 不错的收获。我没有这样想——我猜唯一可以传入两次迭代器同时仍然符合标准的方法是跳过另一个迭代器作为交换;-)
  • @MahmoudAl-Qudsi,是的,我也在考虑这个问题,但实际上只是将两个和两个放在一起符合这一点,以及函数本身的保证行为。
  • 由于 O(kn) 也等于 O(n) 这并不能明确回答问题。
  • @c z:但规范没有使用大 O 表示法,它说复杂性是“准确”的距离。 O(n) 将转换为“与距离成线性比例”,并且将其解读为“确切的距离”是非常不正确的,所以我认为即使它不是完全明确的,它也不会像你暗示的那样模糊。
猜你喜欢
  • 2016-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-23
  • 1970-01-01
相关资源
最近更新 更多