2012-12-14 2 views
0

Я читаю эффективную stl. Я застрял здесь:Как не стирать итератор (от «Эффективный STL»)

assoccontainer<int> c 
for(container<int>::iterator i=c.begin();i!=c.end();++i) 
    if(badvalue(*i)) 
    c.erase(i); 

В чем проблема с данным кодом? Я не понимаю объяснений там.

У меня есть другой вопрос, тоже:

  1. Что делает assoccontainer значит? Я не могу найти какую-либо связанную статью.
  2. badvalue какое-то ключевое слово?
+1

Мое предположение заключается в том, что вы изменяете контейнер во время итерации через набор. Изменения должны выполняться с использованием итератора. – Kotte

+1

Этот вопрос использует своего рода псевдокод, чтобы сделать точку. И когда вы знаете, что вы также знаете ответ на вопрос. Дело в том, что вы вызываете 'erase' на' iterator'. – Dialecticus

+0

Лучшим заголовком для вопроса может быть «Пример книги использует классы, о которых я никогда не слышал», или «Пример, показывающий проблему с стиранием итераторов, не имеет смысла». –

ответ

5

Что означает символ партнера?

Это означает какой-то ассоциативный контейнер, такой как std::set. Обратите внимание, что он напечатан курсивом, что означает, что это не настоящий код, а местозаполнитель для фактического типа контейнера.

Есть ли 'badvalue' какое-то ключевое слово?

Нет, он предназначен для функции, определяемой программой, чтобы определить, должно ли быть удалено значение из контейнера. Он представлен на предыдущей странице, где говорится: «Давайте уничтожим каждый объект, для которого следующий предикат возвращает true».

В чем проблема с данным кодом

Это объясняется в книге, сразу же после того, как образец кода. erase(i) делает недействительным итератор - это значит, что вы больше ничего не можете с ним делать - так что ++i сразу же дает неопределенное поведение. Вместо этого, вы должны использовать код из позже на той же странице:

for (AssocContainer<int>::iterator i = c.begin(); i != c.end(); /* nothing */) { 
    if (badValue(*i)) c.erase(i++); 
    else ++i; 
} 

, который увеличивает iперед тем стиранию и недействительности его старое значение.

+0

Интересно. Как 'c.erase (i ++);' отличается от 'c.erase (i); i ++;'? – Dialecticus

+0

@Dialecticus: первые вызовы «стирают» по старому значению * после * приращения 'i', поэтому' i' сам не является недействительным. Второе дает неопределенное поведение. –

+0

Предположим, что элементы 1,2,3,4,5 говорят, что итератор указывает на 3. Если c.erase (i ++) задано, то 4 удаляется. Где, как и когда второй код указан, 3 удаляется. – Saikiran

2

assoccontainer и badvalue не имеют отношения к основному вопросу. Просто притвориться assoccontainer - это какой-то контейнер, а badvalue - это некоторая функция, возвращающая bool. Основная проблема заключается в использовании итератора после того, как он был использован для удаления элемента. После того, как итератор erase недействителен и больше не может использоваться.

0

assoccontainer является эквивалентом словаря или хэш-карты, хотя автор (Скотт Мейерс?), Возможно, использовал его в общем смысле. AFAIK, в STL нет контейнера с этим именем; замените это на std :: map. Думаю, это должно было сделать трюк.

Вы найдете более подробную информацию об этом здесь: http://en.wikipedia.org/wiki/Associative_containers_(C%2B%2B)

Он имеет аккуратный пример для подсчета вхождений строки.

Скорее всего, Скотт Мейерс имел в виду, что badvalue() является определяемой пользователем функцией, которая определяет, действительно ли значение, де-ссылка на использование итератора, действительна или нет.

HTH.

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