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;
}
数组a中有3个10。
为什么我们用remove函数删除所有10后,数组v中还包含10。
您也可以在这里看到编译的输出
实际上
std::remove
不会从容器中移除该物品。引自这里
Remove 从范围
中删除所有等于[first, last)
的元素。也就是说,remove 返回一个迭代器value
,使得范围new_last
不包含等于[first, new_last)
的元素。value
范围内的迭代器都是仍然可解引用,但它们指向的元素是未指定。Remove是稳定的,这意味着不等于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 惯用法如此常见和有用,因为
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
。
原因是STL算法不会修改序列的大小。
remove
,不是实际删除项目,而是移动它们并将迭代器返回到“新”端。然后可以将该迭代器传递给容器的 erase
成员函数以实际执行删除:
v.erase(std::remove(v.begin(), v.end(), 10), v.end());
顺便说一句,这被称为“擦除删除惯用语”。
编辑:我错了。查看评论和纳瓦兹的回答。
std::erase
,它简化了所有标准库容器的此任务。
此处多个旧答案建议的解决方案:
v.erase(std::remove(v.begin(), v.end(), 10), v.end());
现在可以写成:
std::erase(v, 10);
因为
std::remove
实际上并没有缩小容器,它只是将所有元素向下移动以填充“已删除”元素所使用的位置。例如,如果您有一个序列 1 2 3 4 5
并使用 std::remove
删除值 2
,您的序列将看起来像 1 3 4 5 5
。如果您随后删除值 4
,您将得到 1 3 5 5 5
。在任何时候,序列都不会被告知要短。
C++ 自 2018 年起就有擦除算法(免费函数)https://en.cppreference.com/w/cpp/container/vector/erase2。 这直接作用于容器:
std::erase(v, 10);
这是 C++20 中的。还有一个适用于谓词的版本:
std::erase_if(v, std::less<int>{}(10));