перемещение указателя между векторами в векторе приводит к несовместимости векторных итераторов - PullRequest
1 голос
/ 28 сентября 2011

У меня std::vector клеток. Каждая ячейка имеет другие std::vector для хранения указателей на сущности. Теперь я хочу переместить указатель из одной ячейки в другую на основе расчета индекса новой ячейки. Но я получаю vector iterators incompatible. Я знаю, что это вызвано push_back недействительным итератором, но я не знаю почему, потому что push_back не манипулирует текущими существующими entityIter. Как мне изменить следующий пример, чтобы он работал?

    for(uint32 cellIndex = 0; cellIndex < m_cells.size(); ++cellIndex)
    {
        std::vector<entity_type> & entitiesInCurrentCell = m_cells[cellIndex].entities;
        std::vector<entity_type>::iterator entityIter = entitiesInCurrentCell.begin();
        while(entityIter != entitiesInCurrentCell.end())
        {
            entity_type entity = *entityIter;
            uint32 entityNewIndex = calculateIndex(entity->getPosition());

            if(entityNewIndex == cellIndex) 
            {
                ++entityIter;
                continue;
            }

            m_cells[entityNewIndex].entities.push_back(entity);
            entitiesInCurrentCell.erase(entityIter++);
        }
    }

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

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

спасибо

Ответы [ 2 ]

2 голосов
/ 28 сентября 2011

Строка, которая удаляется из entitiesInCurrentCell, содержит ошибку. Исправьте это, написав

entityIter = entitiesInCurrentCell.erase(entityIter);

При удалении из контейнера следующий итератор возвращается функцией стирания, поэтому вам не нужно увеличивать итератор.

1 голос
/ 28 сентября 2011

Стирание из std :: vector делает недействительными итераторы. см. STL vector :: erase Следовательно, entityIter недействителен после вызова стирания. Увы, проверка "while (entityIter! = EntityInCurrentCell.end ())" никогда не станет истинной.

измените свой код на:

if(entityNewIndex == cellIndex) 
{
  ++entityIter;
}
else 
{
  m_cells[entityNewIndex].entities.push_back(entity);
  entityIter = entitiesInCurrentCell.erase(entityIter);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...