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;
            }
        }
    }
}