简体   繁体   中英

C++ Map/Set iterator Not Incrementable Error

I've been working on this error for awhile now and I'm just not sure how to fix it.

I've got an EntityManager that handles all the entities within the game I'm developing, each entity is added to a map which is sorted by a random ID each entity is given.

void EntityManager::AddEntity(Entity* entity)
{
    int ID = rand();
    for(int i = 0; i < IDS.size(); i++)
    {
        if(IDS[i] == ID)
        {
            ID = rand();
            i = 0;
        }
        else
        {
            break;
        }
}

entity->SetID(ID);
entities.insert(pair<int, Entity*>(ID, entity));

When I want to delete an entity within the game, I simply call this RemoveEntity Function:

void EntityManager::RemoveEntity(Entity* entity)
{
    entities.erase(entity->GetID());
    delete entity;
}

and pass in the entity that is being deleted, normally through "this" like so:

virtual void Effect::RemoveEffect()
{
    DeleteEntity(this);
}

void DeleteEntity(Entity* entity)
{
    entityManager->RemoveEntity(entity);
}

Everything in the game inherits from this Entity Class by the way.

The problem I'm having is this error which occurs when I call the "RemoveEntity" function and it runs this line of code:

entities.erase(entity->GetID());

The game will simply crash with a Map/Set iterator Not Incrementable Error and I just can't figure out why. I've looked at other topics about people having this error but the way they solve it is by making changes to something like a for loop which as you can see... I don't have.

I should note though that this error only occurs so far when I'm deleting an Entity this way:

destroyTimer += deltaTime;
if(destroyTimer >= destroyDelay)
{
    entityManager->RemoveEntity(this);
}

Where I have a timer to delay when the entity is deleted. This section of code is in the Update Function which is called during the GameLoop so every frame. The removing an Entity works without an error when I'm just calling the "RemoveEntity" function instantly without any timer like the one above but I don't see why it would cause the error.

Does anyone know what's going on?

EDIT The RemoveEntity function shown in the example above is within the Update function of an Entity which each Entity Has, the full Update loop looks like this:

void PointEffect::Update(float deltaTime)
{
    Entity::Update(deltaTime);

    destroyTimer += deltaTime;
    if(destroyTimer >= destroyDelay)
    {
        RemoveEffect();
    }
}

The Entity::Update(deltaTime) just calls this:

virtual void Update(float deltaTime)
{
    if(animationHandler != nullptr)
    {
        animationHandler->Update(deltaTime);            
    }

    if(moveSpeed != 0)
    {
        position += velocity * moveSpeed;
    }

    if(collision != nullptr)
    {
        collision->Update(GetSpriteRect(), position);
    }
}

The Update loop found in each entity is called by the actual EntityManagers Update loop which is then called by the GameStates Update function, which is then just called by the GameLoop itself. EntityManager Update Function:

void EntityManager::Update(float deltaTime)
{
if(!entities.empty())
{
        for(const auto entity : entities)
        {           
             entity.second->Update(deltaTime);
        }
    }
}

GameState Update Function:

void MainGame::Update(float deltaTime)
{
    entityManager->Update(deltaTime);
}

You can't delete entity from entities while that for loop in EntityManager::Update is running. That's because the for loop is still using iterators. You'll need to make a note of which entities to delete while the loop is running (and then delete them), or use a traditional for loop and advance the loop iterator to the next element before calling Update (which will only work if you're only not deleting some other entity).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM