如何在使用std::remove_if后使用“已删除”的元素

3

假设我们有以下内容:

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()的元素并不是我们要删除的偶数整数。例如,如果v最初为1 4 2 8 5 7,那么我得到的是这些元素的8 5 7(尽管在erase调用后,vector确实只剩下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.

首先,什么鬼?其次,我如何避免重新实现remove_if而解决这个问题?

如果您正在使用指针容器,则有一个相关的提示 - 如果要使用指针删除,请使用partition:http://www.ddj.com/architect/184401414 - amit kumar
3个回答

7

看起来你想使用partition()将向量分成奇数值开头和偶数值结尾的组。 partition()将返回第二个分组的第一个元素的迭代器。

至于WTF,我不确定为什么你希望删除操作通过将要删除的元素复制到容器的末尾来保留它们(那是额外的工作)。 大多数人认为remove()(以及它的同类)中的WTF是向量的大小没有减小,你必须调用erase()在remove操作后实际删除不需要的元素。


那其实是我的最初的WTF,但我已经习惯了它,并且我没有意识到partition()的存在。 - Jesse Beder
当你思考这个问题时,它是有意义的。迭代器仅表示容器中的序列,而不是容器本身。它可能不代表容器中的每个元素或任何数据。但是,是的,它经常会让新手犯错。然后他们会有一个“恍然大悟”的时刻,理解STL。 - jalf
jalf 是正确的。刚开始很容易感到困惑,但是如果 remove_if() 能够自己清除剩余的元素,那就意味着它无法与数组一起使用。(如何从数组中“删除元素”?) - j_random_hacker
是的,我明白了。我只是假设remove_if函数实际上执行的是partition函数的操作。我的问题在于SGI网站没有在remove_if页面中提到partition函数,所以我无法找到它(或者知道这样一个函数的存在)。 - Jesse Beder

2
我想重点是函数被称为remove_if是有原因的。它删除元素,而不是移动或选择它们。在调用remove_if之后,您不能保证已删除的元素仍然存在。您只能保证firstnew_last之间的元素不包含任何已删除的元素。 std::partition可能是更好的选择,不是吗?或者根据您要做的确切事情,也许可以考虑使用remove_copy_if

2
如果你真的想使用“已移除”的元素,你需要使用 std::partition。 点击此处 了解更多信息。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接