STL erase() 陷阱:迭代器失效解析与避免策略
76 浏览量
更新于2024-09-01
1
收藏 72KB PDF 举报
"STL的erase()函数在删除元素时会导致迭代器失效,尤其是在不同的容器类型中,失效的情况和处理方式有所不同。本文主要探讨了在list、set和map等不同容器中使用erase()的正确与错误示例,并进行了分析。"
在C++的STL中,迭代器是一种用于访问容器内元素的指针类对象。当使用erase()方法删除容器中的元素时,迭代器可能变得无效,这是程序员需要特别注意的问题。
1. **list、set和map容器**
在这些容器中,由于元素存储的方式是链表或者红黑树,因此erase()操作通常不会影响其他元素的位置,所以可以安全地在迭代过程中删除元素。以下是几种常见的使用方法:
- **正确写法1**:在迭代器递增前调用erase(),确保在删除元素后,迭代器已经移动到下一个位置。
```cpp
if (WillDelete(*itList)) {
itList = List.erase(itList);
} else {
itList++;
}
```
- **正确写法2**:在erase()后立即递增迭代器,同样可以避免迭代器失效。
```cpp
List.erase(itList++);
```
- **错误写法1**:在迭代器递增后调用erase(),此时迭代器已经失效,因为erase()会返回新的有效迭代器,而旧的迭代器不再指向任何元素。
```cpp
List.erase(itList); // 这将导致itList失效,因为它指向已被删除的元素
itList++; // 这是错误的,因为itList现在无效
```
- **错误写法2**:在++itList之后立即删除元素,这将导致迭代器在删除前被递增,而实际上我们想删除的是当前迭代器指向的元素。
```cpp
itList = List.erase(++itList); // 先递增再删除,导致错误
```
正确写法1和2在删除元素后都确保了迭代器的有效性,错误写法1和2则会导致程序行为未定义,因为它们尝试使用无效的迭代器。
2. **vector和deque容器**
对于这些按数组存储的容器,erase()操作可能会导致所有后续迭代器失效,因为删除一个元素后,后面的所有元素都需要向前移动。在这种情况下,通常需要重新初始化或获取新的迭代器。
```cpp
std::vector<int> Vec;
std::vector<int>::iterator itVec;
for (itVec = Vec.begin(); itVec != Vec.end(); ) {
if (WillDelete(*itVec)) {
itVec = Vec.erase(itVec);
} else {
++itVec; // 需要检查是否在erase()后重新初始化
}
}
```
总结,理解和正确处理STL容器中erase()操作后的迭代器失效问题是避免程序出错的关键。在删除元素后,必须更新迭代器以保持其有效性。对于按数组存储的容器,如vector和deque,删除操作可能导致大规模的元素移动,因此在迭代过程中删除元素要特别谨慎。而对于list、set和map,由于它们的内部实现,可以在删除元素后安全地更新迭代器。
2020-08-31 上传
点击了解资源详情
2024-03-13 上传
2020-08-31 上传
2011-11-26 上传
2020-08-19 上传
点击了解资源详情
点击了解资源详情
weixin_38687277
- 粉丝: 10
- 资源: 949