究竟什么是“断言”,或者更具体地说,我如何摆脱错误。当我创建一个指向带有数据成员int x的类的指针向量,然后执行以下操作:
for(I=antiviral_data.begin();I<antiviral_data.end();I++)
{
if((*I)->x>maxx)
{
antiviral_data.erase(I);
}
}
运行程序,在x大于maxx并且使用.erase()之前我没有错误,此时我收到此错误:
Debug Assertion失败!
程序:...我的文档\ O.exe文件: ... include \ vector Line:116
表达式: ( “这 - &GT; _Has_container()”,0)
有关您的计划的信息 可能会导致断言失败,请参阅 Visual C ++文档 断言。
(按“重试”调试应用程序)
[中止] [重试] [忽略]
另外,如果我尝试使用cout:
cout<<(*antiviral_data.begin())->x<<endl;
我收到此错误:
Debug Assertion失败!
程序:...我的文档\ O.exe文件: ...包括\ vector Line:98
表达式:不是矢量迭代器 deferencable
有关您的计划的信息 可能会导致断言失败,请参阅 Visual C ++文档 断言。
(按“重试”调试应用程序)
[中止] [重试] [忽略]
有人可以告诉我为什么我不能使用载体中的任何数据,以及如何解决它?
另外:antiviral_data是一个指针向量,只有一个元素:
antiviral_data.push_back(new aX1(player.x,player.y,'>'));
如果有帮助的话。
答案 0 :(得分:11)
你得到断言的最可能的原因是你在擦除后增加了我。试试这个:
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,在该页面上搜索无效迭代器。
答案 1 :(得分:7)
断言通常是开发人员为调试和错误控制目的而输入的表达式 - 您在代码中添加了不同的“健全性检查”,如果未达到检查,则会使程序崩溃。
例如,假设你有一些代码可以将两个数字划分到某个地方。即使你总是期望除以非零,你也可以在除法之前断言,以防参数计算错误。如果断言失败,则意味着在某个地方出现故障。
断言通常只出现在代码中的调试版本中(如果使用visual C ++,则可以编译以进行调试和发布)。虽然在发布模式下进行编译会消除结果,但这是一个非常糟糕的主意,因为您仍然会出现错误并且结果可能非常糟糕。
在Vector的实现中(某些地方是标准的),特别是在第98行中,有一个断言。如果您可以访问向量代码,请查看断言是什么或调试到那一点。这可能表示向量实现或调用向量的代码中的错误。
您发布的内容为我们提供了一些有关正在发生的事情的提示,但如果您可以粘贴更多程序(包括定义矢量的位置),这将非常有用。
答案 2 :(得分:1)
问题在于擦除调用。您正在迭代容器,同时从中删除元素。擦除后,迭代器变为无效。如果要从向量中删除特定值的元素,请使用remove_if算法擦除。这被称为擦除删除习语,并在Scott Meyer的Effective STL书中得到了很好的解释。您还可以参考此问题Erasing elements from a vector以获取更多信息。
答案 3 :(得分: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&lt;&gt; :: remove,它不需要重新定位元素。