2013-10-01 2 views
0

Хорошо, у меня есть список ссылок STL, с которым я перебираю. Эта функция имеет три эквивалентные части. Функция принимает параметр wstring в качестве параметра и запускает соответствующий оператор if. Я сократил код до одного оператора if, чтобы попробовать и заставить его работать.Устранение неполадок элементов через список во время итерации

Итак, я проверяю, что было передано в качестве аргумента. Затем я проверяю, является ли ClassItem определенным типом животного. Если это так, я проверяю, голоден ли он, и удалите его из списка. Я просто пытаюсь избежать seg-сбоев прямо сейчас и не могу это сделать.

list<ClassItem *>::iterator i = Items.begin(); 

    while(i != Items.end())  
    { 
     if(!AnimalType.compare(L"tiger")) 
     { 
      if((*i)->IsAnimalType(L"tiger")) 
      { 
       if((*i)->IsHungry()) 
       { 
        i = Items.erase(i); 

       } 
      } 
      else 
      { 
       ++i; 
      } 
     } 
     // I have tried removing this 
     else 
     { 
     i++; 
     } 
    } 

У меня создалось впечатление, что текущий итератор недействителен, когда я вызываю стирание. Итак, если я стираю элемент, я возвращаю следующий допустимый итератор. Где я иду не так?

EDIT: Благодарим вас за помощь. Проблема была исправлена. Я воспользовался решением для phresnel, и он отлично работал.

+1

Что произойдет, если у вас есть «тигр», который не голоден? Бесконечный цикл, переполнение стека, хаос ... – Gorpik

+1

Что такое AnimalType.compare (L "tiger")? – erenon

+1

этот код сам по себе не должен segfault. пожалуйста, покажите полный пример. –

ответ

0

вы можете добавить

continue; 

после соскабливания.

+0

, а затем проблема все еще существует. –

+0

Почему? После вызова 'erase()' нет инструкций, которые нужно выполнить внутри цикла. – Gorpik

+0

... разрыв не нужен, если OP хочет удалить всех голодных тигров из списка. –

3

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

bool badAnimal(ClassItem * item) 
{ 
    // return true if animal is to be removed 
} 

Items.remove_if(badAnimal); 
+1

это не решит segfault. –

+0

@KarolyHorvath Как это? – juanchopanza

+0

, потому что его код также не должен выполняться. или перефразировать его: почему вы думаете, что это будет? –

1

Я не вижу потенциала для segfault здесь. В любом случае:


Есть (ИМХО) две возможные проблемы:

if(!AnimalType.compare(L"tiger")) 

Это выглядит подозрительным. Что такое AnimalType? Вы действительно ожидаете, что значение if(!AnimalType.compare(L"tiger")) изменится во время итерации, если AnimalType сам делает не?

В любом случае, это похоже на чтение, поэтому не следует писать. Он выглядит постоянным, поэтому не должен меняться.


Тогда:

 if((*i)->IsAnimalType(L"tiger")) 
     { 
      if((*i)->IsHungry()) 
      { 
       i = Items.erase(i); 
      } 
      // NO ITERATION IN CASE OF NOT HUNGRY. 
      // ONCE TRAPPED HERE, YOU HAVE AN INFINITE LOOP, 
      // EXCEPT AnimalType.compare(L"tiger") DOES SOMETHING 
      // NON-SANE. 
     } 
     else 
     { 
      ++i; 
     } 

это должно быть лучше:

 if((*i)->IsAnimalType(L"tiger") && (*i)->IsHungry()) 
     { 
      i = Items.erase(i); 
     } 
     else 
     { 
      ++i; 
     } 

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

Смежные вопросы