STL通过迭代器删除容器内元素会导致迭代器失效,不同的容器会有不一样的迭代器失效情况。
序列式容器包括:vector
,deque
,list
等。
关联式容器包括:set
,multiset
,map
,multimap
,unordered_set
,unordered_multiset
,unordered_map
,unordered_multimap
情况1
对于序列式容器vector
,deque
,比如元素x
对应的迭代器是it
,通过erase(it)
删除元素x
后,不仅元素x对应的迭代器会失效,而且元素x
后面的所有元素对应的迭代器也会失效。但是后边每个元素都会往前移动一个位置,所以erase
会返回下一个有效的迭代。
#include <iostream>
#include <vector>
#include <string>
using namespace std;
void vectorTest() {
vector<int> ve{ 1,2,3,4,5,6,7,8,9 };
cout << "删除前:" << endl;
for (auto v : ve) cout << v << " ";
cout << endl;
auto it = ve.begin() + 3; //元素4对应的迭代器
auto it_next = ve.begin() + 4; //元素4下一个元素对应的迭代器
//通过迭代器删除元素 4
auto it1 = ve.erase(it); //it1是删除当前元素返回的下一个有效的迭代器
//当前删除元素对应的迭代器和其后面元素对应的迭代器都失效了
//cout << "删除的元素:" << *it << endl; //当前迭代器失效,此行报错:引发了异常: 读取访问权限冲突。
//cout <<"删除元素后面元素对应的迭代器"<< *it_next << endl; //it后面的迭代器都失效了,此行报错
cout << "erase删除后返回的下一个有效迭代器对应的元素:"<< *it1 << endl;
cout << "删除后:" << endl;
for (auto v : ve) cout << v << " ";
cout << endl;
}
int main() {
vectorTest();
return 0;
}
执行结果:
情况2
对于关联式容器,通过erase删除元素之后,删除元素对应的迭代器会失效,但是删除元素后面元素对应的迭代器不会失效。而且erase函数也会返回下一个有效的迭代器。
#include <iostream>
#include <set>
#include <string>
using namespace std;
void setTest() {
set<int> s;
for (int i = 1; i <= 9; ++i) {
s.insert(i);
}
cout << "删除前:" << endl;
for (auto it = s.begin(); it != s.end(); ++it) {
cout << *it << " ";
}
cout << endl;
auto it = s.find(5);
auto it_next = s.find(6);//当前迭代器的下一个元素对应的迭代器
auto it2 = s.erase(it);//it2是返回的下一个有效的迭代器
//cout << *it << endl;//报错,当前迭代器失效
cout << "访问删除当前元素的后面元素对应的迭代器:" << *it_next << endl;//说明删除元素后面元素对应的迭代器不会失效
cout << "erase删除后返回的下一个有效迭代器对应的元素:" << *it2 << endl;
cout << "删除后:" << endl;
for (auto it = s.begin(); it != s.end(); ++it) {
cout << *it << " ";
}
cout << endl;
}
int main() {
setTest();
return 0;
}
结果:
其他容器是一样的。
情况3
对于序列式容器list
,因为使用了不连续分配的内存,所以通过erase删除元素之后,删除元素对应的迭代器会失效。但是删除元素后面元素对应的迭代器不会失效。
#include <iostream>
#include <list>
#include <string>
using namespace std;
void listTest() {
list<int> li{ 1,2,3,4,5,6,7,8,9 };
cout << "删除前:" << endl;
for (auto it = li.begin(); it != li.end(); ++it) {
cout << *it << " ";
}
cout << endl;
auto it = find(li.begin(), li.end(), 5);
auto it_next = find(li.begin(), li.end(), 6);
auto it2 = li.erase(it);//删除元素5
//cout << *it << endl;//报错,当前迭代器失效
cout << "访问删除当前元素的后面元素对应的迭代器:" << *it_next << endl;//说明删除元素后面元素对应的迭代器不会失效
cout << "erase删除后返回的下一个有效迭代器对应的元素:" << *it2 << endl;
cout << "删除后:" << endl;
for (auto it = li.begin(); it != li.end(); ++it) {
cout << *it << " ";
}
cout << endl;
}
int main() {
listTest();
return 0;
}
结果: