Почему мой векторный код утверждает? Что такое утверждать в любом случае? - PullRequest
3 голосов
/ 03 мая 2009

Что именно является «утверждать», или, более конкретно, как мне избавиться от ошибки. Когда я создаю вектор указателей на класс с элементом данных 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

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

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

(Нажмите «Повторить» для отладки приложения)

[Прервать] [Retry] [Ignore]

Также, если я попытаюсь использовать cout:

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

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

Ошибка отладочного подтверждения!

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

Выражение: векторный итератор не deferencable

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

(Нажмите Retry для отладки приложения)

[Прервать] [Retry] [Ignore]

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

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

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

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

Ответы [ 4 ]

11 голосов
/ 03 мая 2009

Наиболее вероятная причина, по которой вы получаете утверждение, состоит в том, что вы увеличиваете 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, поиск недействительных итераторов на этой странице.

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

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

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

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

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

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

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

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

0 голосов
/ 03 мая 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, для которого не нужно перемещать элементы.

...