C++ Regarding pointer/reference with remove_if
-
17-04-2021 - |
Question
I'm trying to use remove_if to remove elements in my vector to do filtering. The problem is when I compile the coding, there were no error but when I try to use the filter function, error popped out saying I can't dereference an iterator. I have no idea what is wrong and hope you guys can help spot the problem. Here's partial of my codes
bool filter_C (Teacher &t)
{
return (t.getCat() != compare); //compare is a static string
}
void filterTeacherCategory(vector<Teacher> &t)
{
vector<Teacher>::iterator i;
Teacher *ptr;
i = remove_if(t.begin(), t.end(), filter_C);
ptr = &(*i);
for (i = t.begin(); i != t.end(); ++i)
{
ptr->getName();
cout << "\t";
ptr->getGender();
cout << "\t";
ptr->getPhone();
cout << "\t";
ptr->getCategory();
cout << "\t\t";
ptr->getLocation();
cout << "\n";
}
}
Solution
remove_if returns the new end of the vector. so you should be iterating like so
vector<Teacher>::iterator i;
vector<Teacher>::iterator newenditer = remove_if(..);
for (i = t.begin(); i != newenditer ; ++i)
{
Teacher& tchr= *i;
cout << tchr.getName() << "\n";
cout << tchr.getPhone() << "\n";
}
From remove_if documenation
Applies pred to the elements in the range [first,last), and removes those for which it does not return false from the resulting range. The resulting range consists of the elements between first and the iterator returned by the function, which points to the new end of the range.
The relative order of the elements not removed is preserved, while the elements past the new end of range are still valid, although with unspecified values.
In general it is a good idea to erase the remaining elements after a remove_if
vector<Teacher>::iterator i;
vector<Teacher>::iterator newenditer = remove_if(..);
t.erase( newenditer , t.end() );
Now everything between t.begin() and t.end() is all valid and good so you can do
for (i = t.begin(); i != t.end() ; ++i)
{
}
OTHER TIPS
To actually erase elements, you need to do something like
t.erase(std::remove_if(...),t.end());
remove_if
only provides you with a range (new end) with elements removed. And in your code your ptr
is exactly the new end (that is, one past the last valid element).
This line
ptr = &(*i);
is dereferencing the element after the end of the filtered part of the sequence. If your filter didn't match any elements at all, so nothing was removed, then you're trying to dereference an iterator to one past the end of the vector, which will give the error you report. And even if not the contents of the element pointed to by i
are not likely to be very helpful.
It's not at all clear what you want ptr
to be, but I'm pretty sure it's not this.