Почему мой векторный код утверждает? В любом случае, что такое утверждение?

Что такое «assert», а точнее, как избавиться от ошибки. Когда я создаю вектор указателей на класс с элементом данных int x, а затем делаю следующее:

for(I=antiviral_data.begin();I<antiviral_data.end();I++)
{
    if((*I)->x>maxx)
    {
        antiviral_data.erase(I);
    }
}

И запустите программу, я не получаю ошибок, пока x не станет больше maxx, и я использую .erase (), после чего я получаю эту ошибку:

Ошибка отладки!

Программа: ... Мои документы \ O.exe Файл: ... include \ vector Строка: 116

Выражение: ("this -> _ Has_container ()", 0)

Для получения информации о том, как ваша программа может вызвать сбой утверждения, см. Документацию Visual C ++ по утверждениям.

(Нажмите "Повторить", чтобы отладить приложение)

[Прервать] [Повторить] [Игнорировать]

Кроме того, если я попытаюсь использовать cout:

cout<<(*antiviral_data.begin())->x<<endl;

Я получаю такую ​​ошибку:

Ошибка отладки!

Программа: ... Мои документы \ O.exe Файл: ... include \ vector Строка: 98

Выражение: векторный итератор не распознается

Для получения информации о том, как ваша программа может вызвать сбой утверждения, см. Документацию Visual C ++ по утверждениям.

(Нажмите "Повторить", чтобы отладить приложение)

[Прервать] [Повторить] [Игнорировать]

Не мог бы кто-нибудь сказать мне, почему я не могу ИСПОЛЬЗОВАТЬ какие-либо данные в векторе и как это исправить?

ТАКЖЕ: antiviral_data - это вектор указателей с одним элементом:

antiviral_data.push_back(new aX1(player.x,player.y,'>'));

Если это поможет.


person Community    schedule 03.05.2009    source источник


Ответы (4)


Наиболее вероятная причина, по которой вы получили это утверждение, заключается в том, что вы увеличиваете I после стирания. Попробуйте вместо этого:

for(I=antiviral_data.begin();I!=antiviral_data.end();)
{
    if((*I)->x>maxx) I=antiviral_data.erase(I); else ++I;
}

См. Также http://www.cppreference.com/wiki/stl/vector/erase, найдите на этой странице недопустимые итераторы.

person pts    schedule 03.05.2009
comment
Эмм ... это так же сломано. Как только вы вызываете erase (), последовательность итераций становится недействительной, поэтому любой экземпляр итератора, полученный до изменения контейнера, недействителен. Существует множество способов удаления элементов, но выполнение этого в цикле for, как это, - одна из тех вещей, которые вам не следует делать. - person D.Shawley; 03.05.2009
comment
@ Д.Шоули: Это не совсем так. Да, итераторы до операции стирания недействительны после, но итератор, возвращенный стиранием, действителен. - person Zan Lynx; 03.05.2009
comment
Блин ... хороший момент. Я не заметил задания. Спасибо, Зан. - person D.Shawley; 03.05.2009
comment
Они так уродливо спроектированы эти std :: classes! Я предпочитаю MFC, где я обращаюсь к массиву по индексу. Я просто считаю в обратном порядке сверху вниз, используя стандартный цикл for, удаляю элементы, которые хочу удалить, не нуждаюсь ни в итераторах, ни в других переключателях после удаления. Очень ОПАСНО, что STL заставляет вас манипулировать переменной цикла вручную. В сложных циклах с большим количеством if, else, break, continue может легко случиться так, что в одном месте вы забудете вручную увеличить итератор, и у вас получится бесконечный цикл! - person Elmue; 11.07.2014

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

Например, представьте, что у вас есть код, который собирался разделить два числа где-то в будущем. Даже если вы всегда ожидаете деления на ненулевое значение, вы ставите assert перед делением на случай, если аргумент будет вычислен неправильно. Если утверждение терпит неудачу, это означает, что где-то по дороге произошел сбой.

Утверждения обычно появляются только в отладочной версии кода (если вы используете Visual C ++, вы можете скомпилировать для отладки и выпуска). Хотя компиляция в режиме выпуска приведет к устранению результатов, это очень плохая идея, поскольку вы все равно будете иметь ошибку и, вероятно, действительно плохие результаты.

Где-то в реализации Vector (стандартная ли она) и, в частности, в строке 98 есть assert. Если у вас есть доступ к векторному коду, посмотрите, что это за утверждение, или отлаживайте до этого момента. Это может указывать на ошибку в реализации вектора или в коде, вызывающем вектор.

Материал, который вы опубликовали, дает нам некоторые подсказки о том, что происходит, но было бы полезно, если бы вы могли вставить больше информации о программе, включая места, где определены векторы.

person Uri    schedule 03.05.2009

Проблема с вызовом стирания. Вы просматриваете контейнер и одновременно стираете из него элементы. После стирания ваш итератор становится недействительным. Если вы хотите удалить элементы определенного значения из вектора, используйте стирание с алгоритмом remove_if. Это называется идиомой «стереть-удалить» и очень хорошо объяснено в книге Скотта Мейера «Эффективный STL». Вы также можете обратиться к этому вопросу Удаление элементов из вектора для получения дополнительной информации.

person Naveen    schedule 03.05.2009

У вас уже есть пара хороших ответов о том, что такое утверждение и почему оно запускается в вашем коде. Теперь вы можете рассмотреть возможность использования алгоритмов STL для двухпроходного стирания.

namespace {
   struct exceeds : public std::unary_function< TheUnknownType*, bool >
   {
      exceeds_max( int max ) : maxx( max ) {}
      bool operator()( TheUnknownType* data ) {
         return data->x < max;
      } 
   private:
      int maxx;
   };
}
void your_function()
{
   std::vector< TheUnknownType* >::iterator new_end;
   new_end = std::remove_if( antiviral_data.begin(), antiviral_data.end(), exceeds(maxx) );
   antiviral_data.remove( new_end, antiviral_data.end() );
}

Главное преимущество в том, что стирание элементов вектора - дорогостоящая операция. Для каждого стертого элемента все элементы от этой позиции до конца вектора должны быть перемещены на одну позицию к началу. Второй элемент, который вы удаляете, приведет к второму перемещению всех элементов оттуда ... Алгоритм STL remove_if выполняет перемещения только один раз в их конечную позицию, возвращая итератор один за другим последний элемент не удаленный элемент. Затем вы можете выполнить один единственный std :: vector ‹> :: remove, который не требует перемещения элементов.

person David Rodríguez - dribeas    schedule 03.05.2009