C++ Regarding pointer/reference with remove_if

627 views Asked by At

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";
     }
}
3

There are 3 answers

10
parapura rajkumar On BEST ANSWER

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)
    {
    }
0
Michael Krelin - hacker On

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).

2
Alan Stokes On

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.