文章目录

  • ​​1 erase(搭配迭代器)​​
  • ​​2 remove(搭配值)​​
  • ​​3 在while来使用erase​​


平时一般使用都是vector,但是涉及到频繁删除元素的时候,就会用到list,因为vector每次删除后,删除元素后面的每个元素的迭代器都要重新分配,导致效率低下,而且十分麻烦。但是list使用erase和remove删除元素时,也会存在很多坑。


一下是之前一篇博文中的vector和list删除元素的时间效率比较:

每个测试数据下面的第一行,第二行分别是vector和list
10:
Used time is = 16ms
Used time is = 12ms
100:
Used time is = 526ms
Used time is = 89ms
1000:
Used time is = 28242ms
Used time is = 1334ms
10000:
Used time is = 2532717ms
Used time is = 13984ms
*/
————————————————
版权声明:本文为CSDN博主「繁星蓝雨」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_33375598/article/details/104778027

1 erase(搭配迭代器)

list<int> List;
List.push_back(1);
List.push_back(1);
List.push_back(3);
List.push_back(1);
List.push_back(1);
List.push_back(5);
List.push_back(1);
List.push_back(1);
for (list<int>::iterator i = List.begin(); i != List.end(); ++i) {
if(*i == 1){
List.erase(i);
}
}
for (list<int>::const_iterator i = List.begin(); i != List.end(); ++i) {
if(i != List.begin()) cout <<" ";
cout << *i;
}

上面的代码,大家可能以为会输出1 3 1 5 1

因为大家会认为删除list的一个迭代器后,会让迭代器指向下一个,然后for循环的条件i++,迭代器再往后移动一次,连续的1就会被跳过。 (不成立)

但是实际上会输出:

使用小细节——C++ list的erase和remove_remove

但是实际上,list使用erase删除一个迭代器后,会保留原始索引,仍能输出删除迭代器所指的值,使用erase后返回的是下一个迭代器。

测试程序:

list<int> List;
List.push_back(1);
// List.push_back(1);
List.push_back(3);
List.push_back(1);
List.push_back(1);
List.push_back(5);
List.push_back(1);
List.push_back(1);
for (list<int>::iterator i = List.begin(); i != List.end(); ++i) {

if(*i == 1){
list<int>::iterator temp = List.erase(i);
cout << "temp:" << *temp <<" ";
cout << "i:"<<*i <<" ";
}
}

输出:

使用小细节——C++ list的erase和remove_erase_02

结论是:使用erase后,当前的迭代器不会自动+1。

2 remove(搭配值)

一开始我以为remove(value)只是删除第一个查询到的value,但是实际上它会删除容器中所有value,因此不需要使用for循环,即可删除容器中所有等于value的值。

但是使用remove(value)后,会立即使所有值为value的迭代器全部失效,结果就是,当你再使用失效迭代器时,程序就会报错。

list<int> List;
List.push_back(1);
// List.push_back(1);
List.push_back(3);
List.push_back(1);
List.push_back(1);
List.push_back(5);
List.push_back(1);
List.push_back(1);
for (list<int>::iterator i = List.begin(); i != List.end(); ++i) {
cout << "test:" << *i;
List.remove(1);
}

编译不报错,但是逐步调试就会发现错误:

使用小细节——C++ list的erase和remove_list_03

原因就是使用了失效的迭代器。

3 在while来使用erase

list<int> List, fail;
list<int>::iterator iter = List.begin();
while(iter != List.end()){
if(fgrade(*iter)){
fail.push_back(*iter);
iter = List.erase(iter);
}else{
++iter;
}
}