【问题标题】:How to use the "removed" elements after std::remove_if如何在 std::remove_if 之后使用“已删除”的元素
【发布时间】:2009-01-25 07:37:01
【问题描述】:

假设我们有:

struct IsEven {
   bool operator() (int i) { return i % 2 == 0; }
};

然后:

vector<int> V; // fill with ints
vector<int>::iterator new_end = remove_if(V.begin(), V.end(), IsEven());
V.erase(new_end, V.end());

工作正常(它使V 只剩下奇数)。但似乎从new_endV.end() 的元素不是我们要删除的偶数。例如,如果v1 4 2 8 5 7 开头,那么我将得到这些元素的8 5 7(尽管在erase 调用之后,向量确实有1 5 7 离开)。

显然,(根据http://www.sgi.com/tech/stl/remove_if.html

The iterators in the range [new_last, last) are all still dereferenceable,
but the elements that they point to are unspecified.

首先,WTF?其次,如何在不重新实现remove_if 的情况下解决这个问题?

【问题讨论】:

标签: c++ stl


【解决方案1】:

听起来您想使用partition() 将向量划分为开始时的奇数组和结束时的偶数组。 partition() 将返回一个迭代器,指向第二个分组的第一个元素。

至于 WTF,我不确定为什么您会期望删除操作通过将要删除的元素(这是额外的工作)复制到容器的末尾来保留它们。 大多数人认为remove()(和它的表亲)中的 WTF 是因为向量的大小没有减小,您必须调用 erase() 才能在删除操作后实际删除不需要的元素。

【讨论】:

  • 这其实是我最初的WTF,但我已经习惯了,我并没有意识到partition()的存在。
  • 你仔细想想还是有道理的。迭代器仅表示容器内的序列,而不是容器本身。它可能根本不代表容器中的每个元素,或容器中的数据。但是,是的,它经常绊倒新手。然后他们有一个愉快的时刻,get STL
  • jalf 是对的。最初令人困惑,但如果 remove_if() 本身能够摆脱剩余的元素,则意味着它不能与数组一起使用。 (如何从数组中“删除”元素?)
  • 是的,我明白了。我只是假设 remove_if 做了分区实际做的事情。我的问题是 SGI 站点没有引用分区(来自 remove_if 页面),所以我无法找到它(或者知道存在这样的东西)。
【解决方案2】:

如果你真的想使用“删除”的元素,你需要std::partition

【讨论】:

    【解决方案3】:

    我想关键是该函数被称为remove_if 是有原因的。它删除元素。它不会移动它们或选择它们。调用 remove_if 后,您不再保证删除的元素存在。您可以保证firstnew_last 之间的元素不包含任何已删除的元素。

    std::partition 会是更好的选择,不是吗?或者remove_copy_if,具体取决于您要做什么。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-07
      • 1970-01-01
      • 2019-11-13
      • 1970-01-01
      • 2020-04-23
      相关资源
      最近更新 更多