前言
迭代器失效的问题需要具体情况具体分析:
最重要的是分析容器在内存中的存储方式,判断进行操作之后整个空间有没有被重新分配,或者哪些空间有没有失效。
下面来分析三种不同内存存储方式下的迭代器失效情况:
1.连续内存空间式存储
2.链表式存储
3.红黑树式存储(底层仍为链表存储)
一.连续空间式存储 vector deque
首先要明白vector是顺序式容器,是连续存储空间的。
那么vector中只要erase掉了pos位置的元素,>=pos的迭代器,指针,引用失效,<pos的不失效。
再如push_back,如果空间被重新分配,那么所有的迭代器失效,如果没有重新分配,所有的都有效
同样,deque与vector内存存储类似,便不再过多阐述
void test1() {
vector<int> vec{ 1,2,3,4,5 };
vec.reserve(10);
auto beg = vec.begin();
auto end = --vec.end();
#if 0 //erase
for (auto it = vec.begin(); it != vec.end(); it++) {
if (*it == 3) {
vec.erase(it);
break;
}
}
#endif
#if 1 //push_back
vec.push_back(6);
#endif
cout << *beg << endl;
cout << *end << endl;
}
二.链表式存储 list
由于list内存中存储是双向链表结构,所以erase失效的只有指向删除元素的指针,push_back不会使迭代器失效。
结合双向链表的原理,不难理解。
void test2() {
list<int> vec{ 1,2,3,4,5 };
auto beg = vec.begin();
auto end = --vec.end();
#if 1 //erase
for (auto it = vec.begin(); it != vec.end(); it++) {
if (*it == 3) {
vec.erase(it);
break;
}
}
#endif
#if 0 //push_back
vec.push_back(6);
#endif
cout << *beg << endl;
cout << *end << endl;
}
三.红黑树存储 map set
这两个容器的底层原理是红黑树(实质底层还是指针)
所以当发生erase操作时,只有被删除的元素的迭代器会失效。
insert操作时,迭代器不会失效
void test3() {
set<int> vec{ 1,2,3,4,5 };
auto beg = vec.begin();
auto end = --vec.end();
#if 0 //erase
for (auto it = vec.begin(); it != vec.end(); it++) {
if (*it == 3) {
vec.erase(it);
break;
}
}
#endif
#if 1 //insert
vec.insert(6);
#endif
cout << *beg << endl;
cout << *end << endl;
}