![](/img/trans.png)
[英]In C++, Debug assertion failed window pops up & I get vector iterators incompatible error runtime
[英]Debug Assertion : Vector iterators incompatible (C++)
for (int i = 0; i < m_pGameField->dimensions()->first; i++)
{
for (int j = 0; j < m_pGameField->dimensions()->second; j++)
{
for (std::vector<std::shared_ptr<GameGridElement>>::iterator it = m_pGameField->getField(i, j)->getElements().begin();it != m_pGameField->getField(i, j)->getElements().end(); ++it)
{
if ((*it)->getName().compare("Spawn") == 0)
{
tmpSpawns.push_back(std::static_pointer_cast<SpawnElement>((*it)));
}
}
}
}
大家好,我在上层代码方面遇到了一些问题。 该代码段应能找到2d游戏场中的所有生成物。 当它出现在第三个迭代的开头时,它会发出Debug断言错误,并显示以下消息:“ Vector迭代器不兼容。现在这是崩溃之前的一步。我从Visual Studio调试器中获取了它们:
getElements()返回了{size = 0}; i = 0; j = 0; begin()返回null的struct。 它是NULL结构
我看到向量为空,但是不应该由it!= end()部分处理吗?
您尚未发布足够的代码来确定,但是以下猜测应该是正确的:
getElements()
最有可能通过值而不是通过引用返回。
例如:
std::vector<std::shared_ptr<GameGridElement>> Field::getElements()
{
// ...
return result;
}
这将返回副本 ! 这意味着每次调用getElements
,都会得到一个不同的向量。
对于编译器,这没有任何区别。 类型安全性对您没有帮助,因为std::vector<std::shared_ptr<GameGridElement>>::iterator
是std::vector<std::shared_ptr<GameGridElement>>::iterator
, 即使您有两个迭代器属于不同的容器实例 。 它们具有相同的类型,因此代码可以编译。
但是,在运行时,可以进行其他检查以确保正在比较的两个迭代器确实属于同一容器对象。 这将看似随机的“奇怪”行为或虚假崩溃转变为确定的保证崩溃,以立即告诉您必须修复某些问题。
再次考虑以下这一行:
for (
std::vector<std::shared_ptr<GameGridElement>>::iterator
it = m_pGameField->getField(i, j)->getElements().begin();
it != m_pGameField->getField(i, j)->getElements().end();
++it
)
it
被初始化为getElements().begin()
,然后由!=
与getElements().end()
。 但是如上所述,每个getElements()
返回一个不同的向量,因此您获得了不兼容的迭代器。
这是解决问题的简单方法:
std::vector<std::shared_ptr<GameGridElement>> elements =
m_pGameField->getField(i, j)->getElements();
for (std::vector<std::shared_ptr<GameGridElement>>::iterator it = elements.begin();
it != elements.end(); ++it)
这样可以确保begin()
和end()
将迭代器返回到相同的容器实例。
作为参考,下面是一段简单的代码来重现该行为:
#include <vector>
int main()
{
std::vector<int> v1;
std::vector<int> v2;
bool b = v1.begin() == v2.begin();
}
请注意,C ++标准没有在运行时强制进行迭代器兼容性检查。 您的编译器必须提供它们,并且您必须使用正确的编译器选项来启用它们,或者在不需要或负担不起它们时禁用它们。
顺便说一句,如果您可以使用C ++ 11,则可以使用基于范围的for
循环不仅可以修复错误,还可以使代码更加简洁。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.