Reputation: 161
I am trying to remove some items from a string list in c++. The code compiles successfully but at runtime it gives "Segmentation fault (core dumped)" error. I have abstracted the code as follows.
#include <iostream>
#include <list>
using namespace std;
int main()
{
//a string list
list<string> entries;
//add some entries into the list
entries.push_back("one");
entries.push_back("two");
entries.push_back("three");
entries.push_back("four");
//pass over the list and delete a matched entry
list<string>::iterator i = entries.begin();
while(i != entries.end())
{
if(*i=="two")
entries.erase(i); // *** this line causes the error ***
i++;
}
//print the result
for(const string &entry : entries)
cout<<entry<<"\n";
return 0;
}
Upvotes: 4
Views: 5664
Reputation: 173034
std::list<T,Allocator>::erase
invalidates the iterator to the erased element, i.e. i
. After that the operation like i++
leads to UB.
You can assign it to the return value of erase
, which is iterator following the removed element.
while(i != entries.end())
{
if(*i=="two")
i = entries.erase(i);
else
i++;
}
Upvotes: 5
Reputation: 48297
you can just "remove" the element, no need for iterators, but if you use it, then be aware that erase invalidates the iterator..
#include <iostream>
#include <list>
int main ()
{
//a string list
std::list<std::string> entries;
//add some entries into the list
entries.push_back("one");
entries.push_back("two");
entries.push_back("three");
entries.push_back("four");
entries.push_back("two");
entries.remove("two");
std::cout<<entries.size() << std::endl;
return 0;
}
Upvotes: 2
Reputation: 11950
Erased iterators are invalidated. For your convenience, list::erase
returns next past erased:
if(*i == "two") i = list.erase(i);
else ++i;
Upvotes: 1