C++ 向量迭代器在新对象的push_back()之后不兼容
我有一个C++ 向量迭代器在新对象的push_back()之后不兼容,c++,vector,C++,Vector,我有一个实体类,所有对象(导弹,太空飞船,星星,爆炸)都从该类继承,每当创建这些类的实例时,实体的构造函数都会将“this”添加到所有实例的向量列表中,如下所示: std::vector<Entity*> Entity::instances; Entity::Entity() { instances.push_back(this); } std::vector Entity::instances; 实体::实体() { 实例。推回(此); } 这很好,因为我可以循环遍历每
实体
类,所有对象(导弹
,太空飞船
,星星
,爆炸
)都从该类继承,每当创建这些类的实例时,实体的构造函数都会将“this”添加到所有实例的向量列表中,如下所示:
std::vector<Entity*> Entity::instances;
Entity::Entity()
{
instances.push_back(this);
}
std::vector Entity::instances;
实体::实体()
{
实例。推回(此);
}
这很好,因为我可以循环遍历每个实例,并通过e->Render()或e->Update()等执行其方法
奇怪的是,除了一个特定的地方,它在其他任何地方都有效。
它在这里起作用:
Core.cpp
for(int i=0;i<128;i++)
{
星星[我]=新星();
星[i]->position.x=rand()%(屏幕宽度+1);
星[i]->position.y=rand()%(屏幕高度+1);
星[i]->角度=兰德()%360;
stars[i]->boundingbox.w=2+rand()%7;
stars[i]->boundingbox.h=stars[i]->boundingbox.w;
}
对于(int i=0;i<16;i++)
{
陨石[i]=新陨石();
陨石[i]->Spawn();
}
但是在这里。。它弹出“向量迭代器不兼容”
陨石
void Meteorite::TakeDamage()
{
health -= 5;
if (health <= 0)
{
Missile* explo = new Missile();
explo->position.x = position.x;
explo->position.y = position.y;
Spawn();
}
}
void陨石::TakeDamage()
{
健康-=5;
if(健康位置x=位置x;
expo->position.y=位置.y;
繁殖();
}
}
我完全不懂——我并不是在用一种与通常不同的方式创建这些元素
#编辑
我认为这也很重要,Meteorite::Update()检测碰撞并在创建实例的位置运行TakeDamage():
for each (Entity* e in Entity::instances)
{
if (e == this)
{
continue;
}
if (e->entClass == "ENTITY_MISSILE")
{
Missile* m = (Missile*)e;
if (abs(position.x - m->position.x) * 2 < (boundingbox.w + m-
>boundingbox.w))
{
if (abs(position.y - m->position.y) * 2 < (boundingbox.h + m-
>boundingbox.h))
{
TakeDamage();
break;
}
}
}
}
(实体::实例中的实体*e)
{
如果(e==这个)
{
持续
}
如果(e->entClass==“实体_”)
{
导弹*m=(导弹*)e;
如果(abs(position.x-m->position.x)*2<(boundingbox.w+m-
>边界框(w)
{
如果(abs(position.y-m->position.y)*2<(boundingbox.h+m-
>边界框(h))
{
TakeDamage();
打破
}
}
}
}
尝试:for(Entity*e:Entity::instances)
而不是你的for每个东西注意,当你调用时,迭代器会失效(强调我的):
如果新的size()大于capacity(),则所有迭代器和引用(包括结束迭代器的过去部分)都将无效。否则,只有结束迭代器的过去部分将无效
因此,在调用TakeDamage
时的for
循环中,您构建了一个导弹
(随后调用Entity::Entity()
和实例。推回(this)
),您正在使迭代器无效
您需要通过索引而不是迭代器进行循环,或者跟踪哪些对象需要对其调用TakeDamage()
,并在完成迭代后调用它们,或者创建迭代的实例的副本
请注意,我从未见过每个(…in…
的语法,但可能它使用的是迭代器
您提到问题中的代码是在Meteorite::Update中运行的,您还提到
这很好,因为我可以循环遍历每个实例,并通过e->Render()或e->Update()等执行其方法
很可能你正在迭代所有的实例
,调用更新
,并且在调用TakeDamage
的过程中,这会使你的实例失效。在迭代实例
的过程中调用push_back
,这肯定是你的问题。同样。我确实没有我想这不是对象本身的问题,我可以在其他地方创建它,它工作得很好。比如什么?错误是完全模糊的,只指向向量本身的代码。比如在每行向量操作之前和之后打印出不同的数字,看到最后打印出的数字。然后,找到准确的行错误发生的位置。try:'for(Entity*e:Entity::instances)'我认为在迭代时不能更改…请尝试以下操作:for(auto it=Entity::instances.begin();it!=Entity::instances.end();it++)@ Netheous——不,它不是C++。它是一种奇怪的语法,可能是一个特定的编译器支持的。但是它在其他任何地方都适用,它为创建对象而工作。我们在什么地方、什么时候、什么时候调用这些函数没有上下文。这就是你帖子中缺少的东西。在更改您正在迭代的容器时删除一个容器。这会导致灾难。@Netheous——什么是Spawn
?另外,我们如何知道您的类型是smail
,从而在此处执行不安全的强制转换smail*m=(smail*)e、
?如果有什么问题,您应该发出一个动态\u cast
,以确保您没有犯错误。@passway--是的,宏是邪恶的。用下面NL628所说的替换它仍然会弹出相同的错误。@Netheous--如果您所做的是这个答案所暗示的,那么这就是问题所在。您正在更改您所依赖的容器n“稳定”在该for
语法中。这将无法正常工作。事实上,在迭代时,您无法更改在基于范围的for
循环中指定的容器,但您这样做了。@PaulMcKenzie我也遵循了TA给出的建议。我创建了一个bool collide=false;然后在for循环中,我是chec国王是否发生碰撞——如果设置为冲突,则设置为true并中断;之后为循环运行TAG DATA();如果发生冲突。相同的错误。如果只调用<代码> TakeDamage <代码>触发错误,那么考虑更新您的问题,这样做,而不是包括什么是多余的周围代码。
for each (Entity* e in Entity::instances)
{
if (e == this)
{
continue;
}
if (e->entClass == "ENTITY_MISSILE")
{
Missile* m = (Missile*)e;
if (abs(position.x - m->position.x) * 2 < (boundingbox.w + m-
>boundingbox.w))
{
if (abs(position.y - m->position.y) * 2 < (boundingbox.h + m-
>boundingbox.h))
{
TakeDamage();
break;
}
}
}
}