Срок действия итератора, указывающего на стертый элемент - PullRequest
2 голосов
/ 21 марта 2011

На этой странице сказано, что:

делает недействительным весь итератор и ссылки на элементы после позиции или первого.

Делает ли этоозначает, что итераторы position и first действительны после стирания?

(Очевидно, я спрашиваю об этом, потому что хочу удалить какой-либо элемент в векторе во время цикла for_each.)

Спасибовы.

Ответы [ 5 ]

2 голосов
/ 21 марта 2011

В соответствии с http://www.open -std.org / jtc1 / sc22 / wg21 / docs / lwg -fects.html # 414 positon и first следует считать недействительными - формулировка вСтандарт неясен, но поскольку итераторы и ссылки упоминаются в одном предложении, а ссылка на стертый элемент не имеет смысла, то это "принимается как должное", когда стираются недействительные итераторы, указывающие на стертый элемент.Я бы не стал полагать, что стертый итератор действителен - когда вы удаляете begin() из вектора с одним элементом, я не воспринимаю как должное то, что итератор внезапно равен end()

2 голосов
/ 21 марта 2011

Часто, если вы пытаетесь удалить несколько элементов из vector в цикле, использование remove_if даст вам лучшую производительность, чем использование erase для каждого элемента. Рассмотрите это, а не повторяйте-стирайте.

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

0 голосов
/ 21 марта 2011

Это то, что говорится, но это неправильно.Согласно стандарту, они недействительны (что имеет смысл, поскольку для того, чтобы оставаться действительным, они должны указывать на элемент, которого там больше нет).

0 голосов
/ 21 марта 2011

Если вы стираете во время итерации, рассмотрите следующий синтаксис:

vector<int> items = ...;

for(vector<int>::iterator it = items.begin() ; it != items.end() ; /*inline*/)
{
   if(/* should erase*/)
      it = items.erase(it);
   else
      ++it;
}

Это работает, потому что erase() возвращает итератор к следующему элементу после текущего. Таким образом, если вы удалили, он «увеличивается», в противном случае вы увеличиваете его как обычно. Как уже отмечали другие, это не очень эффективно (поскольку все элементы после текущего копируются вперед), и есть более эффективные способы. Например, как отмечалось в отметке B, может быть лучше использовать remove_if.

0 голосов
/ 21 марта 2011

Да. Но они не будут ссылаться на тот же элемент, что и до erase(), потому что этот элемент будет удален!

...