或许STL的设计者认为API的一致性很重要,函数名短而美很重要,人的脑容量不重要……
首先明确两点:
由于STL的算法模块设计是与具体的容器类型是解耦的,也就是说,它只接收各类容器的迭代器并操作,而迭代器又隐藏了容器中元素迭代的具体细节,所以std::remove无法真正的删除元素,因为它只知道容器的迭代器,根本不知道容器的erase方法。
对于连续内存容器,std::remove和std::remove_if的行为是把符合条件的元素全部移到容器的最末尾,并返回第一个待删除元素的迭代器。此时通过erase方法将这些元素都真正的删除掉即可。示例代码如下:
vector<int> vi{1,2,2,3,4,5,6,6};
vi.erase(remove(vi.begin(), vi.end(), 2), vi.end()); // 不使用erase的返回值
vi.erase(remove_if(vi.begin(), vi.end(), [](int i){ // 不使用erase的返回值
return i > 4;
}), vi.end());
自然很容易联想到for配合erase来删除啦。但是对于连续内存容器,调用erase删除单个元素使后面元素的迭代器失效后(当然被删除那个也失效了),循环还在跑,对被删除的失效迭代器又自加了,行为未定义。所以要利用erase的返回值:
vector<int> vi{1,2,2,3,4,5,6,6};
for(auto iter = vi.begin(); iter != vi.end(); /*这里啥也不干*/)
{
if(*iter == 2)
{
iter = vi.erase(iter); //这里隐含了一次++
}
else
{
++iter;
}
}
list使用连续内存容器的区间删除和迭代删除方式都可以,但更为高效的是直接调用list::remove()函数,因为对于链表来说,把所有的待删除值扔后面再统一删除太浪费,链表删除单个元素是O(1)。
总感觉STL这里有点过度设计的意思……(逃
原文:https://www.cnblogs.com/jo3yzhu/p/12705988.html