Что означает этот код в "векторе"? (C ++) - PullRequest
1 голос
/ 15 мая 2009

Я создал программу, и она использует vector.h #include, итераторы и т. Д. Но когда я запускаю программу при определенных обстоятельствах (я все еще пытаюсь выяснить, что это будет) получаю ошибку подтверждения, ссылающуюся на строку 98 вектора.h. Я пошел в строку 98 вектора.h и получил это:

 #if _HAS_ITERATOR_DEBUGGING
        if (this->_Mycont == 0
            || _Myptr < ((_Myvec *)this->_Mycont)->_Myfirst
            || ((_Myvec *)this->_Mycont)->_Mylast <= _Myptr)
            {
            _DEBUG_ERROR("vector iterator not dereferencable");
            _SCL_SECURE_OUT_OF_RANGE;
            }

Может кто-нибудь сказать, что это значит и что в моей программе вызывает это утверждение?

Примечание: для записи строка 98 начинается с _DEBUG_ERROR ("vect ..."

NB. Это код в моей программе, который, как я полагаю, вызвал ошибку, хотя я не совсем уверен.

КОД:

for(aI = antiviral_data.begin(); aI < antiviral_data.end();)
    {
        for(vI = viral_data.begin(); vI < viral_data.end();)
        {
            if((*aI)->x == (*vI)->x && (*aI)->y == (*vI)->y)
            {
                vI = viral_data.erase(vI);
                aI = antiviral_data.erase(aI);
            }
            else
            {
                vI++;
            }
        }
        if((*aI)->x >= maxx || (*aI)->x < 0 || (*aI)->y >= maxy || (*aI)->y < 0)
        {
            aI = antiviral_data.erase(aI);
        }
        else
        {
            aI++;
        }
    }

Ответы [ 5 ]

10 голосов
/ 15 мая 2009

Среда выполнения обнаруживает, что вы разыменовываете итератор, который находится перед begin () или после end ().

Представьте, что вы удаляете последний элемент вектора antiviral_data в строке 7:

aI = antiviral_data.erase(aI);

aI устанавливается на antiviral_data.end(), а при разыменовании его в строке 14:

if((*aI)->x >= maxx ...

, а также в строке 5:

if((*aI)->x == (*vI)->x

Вы разыменовываете итератор вне границ.

Исправлено - проверка aI != antiviral_data.end() после вызова стирания, чтобы убедиться, что вы не достигли конца вектора, прежде чем продолжать его использовать.

7 голосов
/ 15 мая 2009

Вы действительно хотите смотреть на алгоритмы STL как remove_if вместо того, чтобы делать это вручную.

5 голосов
/ 15 мая 2009

Небольшое общее замечание: при проверке итератора на end() не используйте "<", а только "!=". Итак, первые строки вашего кода должны выглядеть так:

for(aI = antiviral_data.begin(); aI != antiviral_data.end();)
{
  for(vI = viral_data.begin(); vI != viral_data.end();)
  {
    ...

Однако, как уже указал Джош, ваша конкретная ошибка находится в строке 7.

1 голос
/ 15 мая 2009

Помимо принятого ответа и уточнения ответа slavy13 -
( РЕДАКТИРОВАТЬ - и, как упоминал Джош, не имеет прямое отношение к этому вопросу - я оставляю его здесь для справки).

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

Причина этого в том, что вектор на самом деле хранит информацию в виде массива. Когда элемент удаляется, все последующие элементы копируются на одну ячейку вниз. Соответственно, итераторы не обновляются.

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

0 голосов
/ 15 мая 2009

Стирание элемента в векторе делает недействительными все итераторы.

...