array/vector/deque
这三种容器的内存空间连续,删除某一元素会导致其后所有元素前移。
如图所示,删除某一元素后,后面的元素全都前移了一位。此时it3指向end位置。
依照C++规定,包括it0在内的其后迭代器全部“失效”(尽管他们有些指向的是有效位置),对这些迭代器进行任何操作(解引用、调用符号重载函数等)都会抛出错误。
解决方法:erase函数将返回下一个有效位置的迭代器
例如:
//删除2之前的所有元素
vector<int> vec{ 0,1,2,3 };
for (auto it = vec.begin(); *it != 2;)
it = vec.erase(it);
list
对于使用链式存储结构的list,删除元素时就没有那么多顾虑了。
//删除2之前的所有元素
list<int> ls{ 0,1,2,3 };
for (auto it = ls.begin(); *it != 2;)
it = ls.erase(it);//ls.erase(it++)也可以
Q:为什么对于array/vector/deque删除元素时不能使用erase(it++)?
A:由于上述容器删除元素后其后元素将前移,所以erase(it++)将使it“后移”两格,这显然不符合it++的初衷,所以C++规范禁用了这一做法。
vec.erase(it++)语句不会报错,但之后一旦使用it就会抛出错误。
set/map
使用红黑树的set/map,本质上也是链式的存储结构,所以其迭代器失效情况同list
//删除2之前的所有元素
set<int> s{ 0,1,2,3 };
for (auto it = s.begin(); *it != 2;)
it = s.erase(it);//s.erase(it++)也可以