I experimented the following code
list<int> a ={1,2};
list<int> b ={3,4};
a.erase(b.begin());
for (auto x:b) cout << x << endl;
Strangely, the program ran fine without any error. What it prints out is 4. I wonder why erase is a member function when the object is already implicit in the iterator.
a.erase(b.begin());
This invokes undefined behavior, because you're passing iterator obtained from one container to a function of other container. a
and b
are two different containers, they're not same.
Undefined behavior means anything could happen: it may run as expected, or it may not. Neither the language specification nor the compiler gives guarantee that it will work. It is aptly said "undefined behavior".
What you should do is this:
auto value = *(b.begin()); //value is int
auto it = std::find(a.begin(), a.end(), value); //returns iterator
if ( it != a.end())
a.erase(it); //well-defined, as the iterator belongs to the same container!
Or, if you want to remove all elements equal to value
, then you could simply do this:
a.remove(value); //std::list has remove member function
However, if you use std::vector
which you should be using in most cases. It is default container type in C++, and you should use std::list
only if you've strong reason to do so:
std::vector<int> a ={1,2};
std::vector<int> b ={3,4};
//if you want to remove one element:
auto value = *(b.begin()); //value is int
auto it = std::find(a.begin(), a.end(), value); //returns iterator
if ( it != a.end())
a.erase(it); //well-defined, as the iterator belongs to the same container!
And if you want to remove all elements equal to value
, then you can apply popular Erase-Remove Idiom as:
a.erase(std::remove(a.begin(), a.end(), value), a.end());
Note that std::vector
doesn't have remove()
member function, that is why you apply this idiom. You can read my answer here which discusses about this in more detail.