Сохранение допустимого вектора :: iterator после erase ()

РЕДАКТИРОВАТЬ: У меня было много ответов, в которых говорилось, что я должен разделить удаление в другой цикл . Возможно, я недостаточно прояснил это, но в последнем абзаце я заявил, что хотел бы найти иное решение. то есть сохраняя текущую структуру кода, но используя малоизвестную фу C ++ для ее работы.

Я знаю, что вызов erase () для вектора делает недействительными итераторы для элемента и все следующие за ним, и что erase () возвращает итератор к следующему действующему итератору, но что, если стирание произойдет где-то еще?

У меня следующая ситуация (упрощенная):

ПРЕДУПРЕЖДЕНИЕ. НЕ предполагайте, что это весь код. То, что показано ниже, ЧРЕЗВЫЧАЙНО упрощено для иллюстрации моей проблемы. Все классы и методы, показанные ниже, на самом деле намного сложнее.

class Child {
   Parent *parent;
}

class Parent {
   vector<Child*> child;
}

void Parent::erase(Child* a) {
   // find an iterator, it, that points to Child* a
   child.erase(it);
}

int Child::update() {
   if(x()) parent.erase(*this) // Sometimes it will; sometimes (most) it won't
   return y;
}

void Parent::update() {
   int i = 0;
   for(vector<A>::iterator it = child.begin(); it != child.end(); it++)
      i += (*it)->update();
}

Таким образом, очевидно, что он выйдет из строя после запуска (* it) -> update () if x () возвращает истину, потому что, когда это произойдет, Ребенок скажет Родителю удалить его из вектора, аннулируя итератор.

Есть ли какой-либо способ исправить это, кроме как заставить Parent :: erase () передать итератор вплоть до Parent :: update () ? Это было бы проблематично, так как она вызывается не для каждого вызова Child :: update () , и, таким образом, этой функции потребуется способ возвращать себе итератор каждый раз, а также в настоящее время возвращает другое значение. Я также предпочел бы избежать другого подобного способа отделения процесса стирания от цикла обновления.

11
задан Infiltrator 23 May 2011 в 12:50
поделиться