3

究竟什么是“断言”,或者更具体地说,我如何摆脱错误。当我创建一个指向具有数据成员 int x 的类的指针向量时,然后执行以下操作:

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

并运行程序,直到 x 大于 maxx 并且我使用 .erase() 之前我没有收到任何错误,此时我收到此错误:

调试断言失败!

程序:...My Documents\O.exe 文件:...include\vector 行:116

表达式:("this->_Has_container()",0)

有关您的程序如何导致断言失败的信息,请参阅有关断言的 Visual C++ 文档。

(按重试调试应用程序)

[中止][重试][忽略]

另外,如果我尝试使用 cout:

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

我收到此错误:

调试断言失败!

程序:...My Documents\O.exe 文件:...include\vector 行:98

表达式:向量迭代器不可延迟

有关您的程序如何导致断言失败的信息,请参阅有关断言的 Visual C++ 文档。

(按重试调试应用程序)

[中止][重试][忽略]

有人可以告诉我为什么我不能使用向量中的任何数据,以及如何解决它?

还:antiviral_data 是一个指针向量,只有一个元素:

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

如果这有帮助。

4

4 回答 4

11

你得到断言的最可能的原因是你在擦除后增加了 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,在该页面上搜索无效迭代器

于 2009-05-03T16:33:02.143 回答
7

断言通常是开发人员出于调试和错误控制目的输入的表达式 - 您在代码中放置了不同的“健全性检查”,如果未达到检查,则让程序崩溃。

例如,假设您有一段代码要在某处将两个数字相除。即使您总是期望除以非零,您也可以在除法之前加上 assert,以防参数计算错误。如果断言失败,则意味着在路上的某个地方发生了故障。

断言通常仅出现在代码中的调试版本中(如果您使用 Visual C++,则可以编译以进行调试和发布)。虽然在发布模式下编译会消除结果,但这是一个非常糟糕的主意,因为您仍然会遇到错误并且可能会产生非常糟糕的结果。

在 Vector 实现的某个地方(它是标准的),特别是在第 98 行,有一个断言。如果您有权访问向量代码,请查看断言是什么或调试到该点。这可能表示向量实现或调用向量的代码中存在错误。

您发布的内容为我们提供了一些关于正在发生的事情的提示,但如果您可以粘贴更多程序,包括定义向量的位置,将会很有用。

于 2009-05-03T16:29:18.283 回答
1

问题在于擦除呼叫。您正在遍历容器并同时从中删除元素。执行擦除后,您的迭代器变得无效。如果要从向量中删除特定值的元素,请使用带有 remove_if 算法的擦除。这被称为擦除删除习语,并在 Scott Meyer 的 Effective STL 书中得到了很好的解释。您还可以参考这个问题从向量中擦除元素以获取更多信息。

于 2009-05-03T16:38:38.323 回答
0

关于什么是断言以及为什么在代码中触发它,您已经有了几个很好的答案。现在,您可能需要考虑使用 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 。

于 2009-05-03T18:05:21.890 回答