Подтвердить что ты не робот

Какое распространенное злоупотребление использованием контейнеров STL с итераторами?

Какое распространенное неправильное использование контейнеров STL с итераторами?

4b9b3361

Ответ 1

Забыть, что итераторы довольно часто недействительны, если вы меняете контейнер, вставляя или стирая элементы контейнера.

Для многих замечательных советов по использованию STL я высоко рекомендуем книгу Скотта Мейерса "Эффективный STL" (санированная ссылка Amazon)

Ответ 2

Проверка концевого диапазона должна использоваться!= и не указывать, так как порядок указателей не гарантируется.

Пример:

for(it = list.begin(); it != list.end(); ++it)
{
     // do stuff
}

Ответ 3

Пост-приращение при предварительном приращении будет выполняться.

Ответ 4

Несколько других:

  • Преобразование обратного итератора в базовый итератор, не забывая, что итератор теперь будет одним элементом за пределами того, на который он указывал.

  • Попытка использовать алгоритмы, требующие итератора с произвольным доступом, с итераторами таких вещей, как наборы и карты.

  • Редактирование ключа записи карты с помощью неконтинентального итератора (это происходит для сборки на VS.Net, но не с GCC)

Ответ 5

Используя их, не прочитав книгу "Эффективный STL" Скотта Мейерса.:) В самом деле. Это заставляет большинство глупых ошибок уходить.

Ответ 6

Собственное продолжение после erase().

Предполагая, что:

Container::iterator i = cont.begin(), iEnd = cont.end();

Например, на std::map это не очень хорошая идея:

for (; i != iEnd; ++i) {
    if (i->second.eraseCondition()) {
        cont.erase(i);
    }
}

Это будет работать:

for (; i != iEnd; ) {
    Container::iterator temp = i;
    ++temp;
    if (i->second.eraseCondition()) {
        cont.erase(i);
    }
    i = temp;
}

И это также:

for (; i != iEnd; ) {
    if (i->second.eraseCondition()) {
        cont.erase(i++);
    }
    else {
        ++i;
    }
}

Было слишком много раз, что мне пришлось применять эти исправления в каком-то производственном коде: (

Ответ 7

Использование auto_ptr внутри контейнера, например

list<auto_ptr<int> > foo;

К счастью, в наши дни много реализаций auto_ptr написано, чтобы сделать это невозможным.

Ответ 8

Это не только проблема с контейнерами STL - контейнером для модификации, когда итерация по ней почти всегда приводит к проблемам.

Это очень распространенный источник ошибок в играх - большинство игровых циклов состоит из итерации над каждым игровым объектом, который что-то делает. f это что-то добавляет или стирает элементы из контейнера игровых объектов, есть почти уверенная ошибка.

Решение - есть два контейнера - objectsToDelete и objectsToAdd - в игровом коде добавить объекты в эти контейнеры и обновить контейнер игровых объектов только после того, как вы повторили его.

objetsToAdd может быть установлен для обеспечения того, что мы не удалим ничего более одного раза.

objectsToDelete может быть Очереди, если вы можете построить объект, не добавляя его в контейнер игровых объектов, или это может быть какой-то другой класс (ObjectCreateCommand?), если ваш код предполагает, что экземпляр объекта всегда добавляется в контейнер игровых объектов непосредственно после создания (для пример в конструкторе).

Ответ 9

list<int> l1, l2;
// ...

for_each(l1.begin(), l2.end(), do_it());