C ++ Относительно указателя / ссылки с remove_if - PullRequest
1 голос
/ 18 января 2012

Я пытаюсь использовать remove_if для удаления элементов в моем векторе, чтобы выполнить фильтрацию.Проблема в том, что когда я компилировал код, ошибок не было, но когда я пытался использовать функцию фильтра, выскочила ошибка, говорящая, что я не могу разыменовать итератор.Я понятия не имею, что не так, и надеюсь, что вы, ребята, можете помочь определить проблему.Вот часть моих кодов

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 ]

2 голосов
/ 18 января 2012

Чтобы действительно стереть элементы, вам нужно сделать что-то вроде

t.erase(std::remove_if(...),t.end());

remove_if предоставляет вам только диапазон (новый конец) с удаленными элементами. И в вашем коде ваш ptr - это точно новый конец (то есть один после последнего действительного элемента).

1 голос
/ 18 января 2012

Эта строка

ptr = &(*i);

разыменовывает элемент после окончания отфильтрованной части последовательности. Если ваш фильтр вообще не соответствует никаким элементам, поэтому ничего не было удалено, то вы пытаетесь разыменовать итератор до конца после вектора, что выдаст ошибку, о которой вы сообщаете. И даже если не содержимое элемента, на который указывает i, вряд ли будет очень полезно.

Не совсем понятно, кем вы хотите ptr, но я уверен, что это не так.

1 голос
/ 18 января 2012

remove_if возвращает новый конец вектора. так что вы должны повторять как

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

}

С remove_if документация

Применяет pred к элементам в диапазоне [first, last) и удаляет те, для которых он не возвращает false, из результирующего диапазона. Результирующий диапазон состоит из элементов между first и итератором, возвращаемым функцией, которая указывает на новый конец диапазона.

Относительный порядок элементов, которые не были удалены, сохраняется, в то время как элементы после нового конца диапазона остаются в силе, хотя и с неопределенными значениями.

В общем, хорошая идея - удалить оставшиеся элементы после remove_if

vector<Teacher>::iterator i;
vector<Teacher>::iterator newenditer = remove_if(..);
t.erase( newenditer , t.end() );

Теперь все между t.begin () и t.end () все корректно и хорошо, так что вы можете сделать

 for (i = t.begin(); i != t.end() ; ++i)
    {
    }
...