int main()
{
const int SIZE = 10;
int a[SIZE] = {10, 2, 35, 5, 10, 26, 67, 2, 5, 10};
std::ostream_iterator< int > output(cout, " ");
std::vector< int > v(a, a + SIZE);
std::vector< int >::iterator newLastElement;
cout << "contents of the vector: ";
std::copy(v.begin(), v.end(), output);
newLastElement = std::remove(v.begin(), v.end(), 10);
cout << "\ncontents of the vector after remove: ";
//std::copy(v.begin(), newLastElement, output);
//this gives the correct result : 2 35 5 26 67 2 5
std::copy(v.begin(), v.end(), output);
//this gives a 10 which was supposed to be removed : 2 35 5 26 67 2 5 2 5 10
cout << endl;
return 0;
}
阵列中有三个10。
为什么在我们删除带有删除功能的所有10个数组后,数组v包含10。
您还可以看到已编译的输出here
答案 0 :(得分:27)
实际上std::remove
不会从容器中删除该项目。引自here
从
[first, last)
范围内移除所有等于value
的元素。也就是说,remove返回迭代器new_last
,使得范围[first, new_last)
不包含等于value
的元素。 范围[new_last, last)
中的迭代器都仍可解除引用,但它们指向的元素是未指定。删除是稳定的,意味着不等于值的元素的相对顺序不变。
也就是说,std::remove
仅适用于一对迭代器,并且对实际包含这些项的容器一无所知。实际上,std::remove
不可能知道底层容器,因为它无法从一对迭代器中发现迭代器所属的容器。所以std::remove
并没有真正删除这些项目,只是因为它不能。 实际从容器中删除项目的唯一方法是调用该容器上的成员函数。
因此,如果您要删除这些项目,请使用Erase-Remove Idiom:
v.erase(std::remove(v.begin(), v.end(), 10), v.end());
erase-remove idiom非常常见且有用的是std::list
添加了另一个名为list::remove
的成员函数,它产生与erase-remove
成语相同的效果。
std::list<int> l;
//...
l.remove(10); //it "actually" removes all elements with value 10!
这意味着,在使用erase-remove
时,您不需要使用std::list
惯用法。您可以直接调用其成员函数list::remove
。
答案 1 :(得分:11)
原因是STL算法不会修改序列的大小。 remove
,而不是实际删除项目,移动它们并返回迭代器到“新”结束。然后可以将迭代器传递给容器的erase
成员函数以实际执行删除:
v.erase(std::remove(v.begin(), v.end(), 10), v.end());
顺便说一句,这被称为“擦除 - 删除成语”。
编辑:我错了。请参阅评论和Nawaz的回答。答案 2 :(得分:1)
因为std::remove
实际上没有收缩容器,所以它只是向下移动所有元素以填充“removed”元素使用的点。例如,如果您有序列1 2 3 4 5
并使用std::remove
删除值2
,则您的序列将显示为1 3 4 5 5
。如果您删除了值4
,则会获得1 3 5 5 5
。在任何时候,序列都不会被告知更短。