STL使用迭代器遍历和删除元素
STL使用迭代器遍历和删除元素
vector 迭代器使用不当造成挂死或死循环
错误用法
#include <vector>
void vec_erase_item(std::vector<int>& vec, int value){
for(auto iter = vec.begin(); iter != vec.end(); iter++){
printf("iter: %p, end(): %p\n", iter, vec.end());
if(*iter == value){
vec.erase(iter);
printf("after erase, iter: %p, end(): %p\n", iter, vec.end());
}
}
}
int main(int argc, char** argv)
{
std::vector<int> vec{0, 2, 4, 6, 8, 10, 1 ,3, 5, 7, 9};
vec_erase_item(vec, 9);
return 0;
}
运行结果:
当要删除的元素刚好是最后一个时,删除后相当于
iter = vec.end();
vec.end() = vec.end() - 1;
所以iter != vec.end()的条件是永远成立的,如果循环中没有对iter进行解引用(*iter),那么会造成死循环,否则,当访问了非法地址,会导致程序挂死。
正确用法
void vec_erase_item(std::vector<int>& vec, int value){
for(auto iter = vec.begin(); iter != vec.end(); ){ // 此处不加iter++
printf("iter: %p, end(): %p\n", iter, vec.end());
if(*iter == value){
iter = vec.erase(iter);
printf("after erase, iter: %p, end(): %p\n", iter, vec.end());
} else{
iter++;
}
}
}
运行结果:
vector erase 返回的迭代器指向下一元素,当删除的是尾元素时,返回的迭代器指向end()。
map 迭代器使用不当造成挂死
错误用法
#include <map>
void map_erase_item(std::map<int, int>& table, int value){
for(auto iter = table.begin(); iter != table.end(); iter++){
if(iter->second == value){
table.erase(iter);
}
}
}
int main(int argc, char** argv)
{
std::map<int, int> table = {
{1, 100},
{2, 200},
{3, 300},
};
map_erase_item(table, 300);
return 0;
}
程序执行后出现挂死,原因是map erase后迭代器已经失效,此后对迭代器的操作是未定义行为。
正确用法
void map_erase_item(std::map<int, int>& table, int value){
for(auto iter = table.begin(); iter != table.end(); ){ // 此处不加iter++
if(iter->second == value){
table.erase(iter++);
// iter = table.erase(iter); // 也可以用这种写法
} else{
iter++;
}
}
}
table.erase(iter++),相当于
auto tmp = iter + 1;
table.erase(iter);
iter = tmp;
table.erase(iter++) 也可以换为 iter = table.erase(iter); 的写法,erase返回的迭代器指向下一个元素。
本文来自博客园,作者:流翎,转载请注明原文链接:https://www.cnblogs.com/hjx168/p/16974537.html