【问题标题】:Adding an object to a vector in the middle of an iteration error在迭代错误中间向向量添加对象
【发布时间】:2021-03-19 07:13:33
【问题描述】:

好吧,我正处于一个循环的中间,该循环迭代一个向量中的所有对象:

for (auto &itr : m_entities) {
    itr.second->Update(l_time);
    if (itr.second->m_isDead) 
        Remove(itr.first); //don't worry, it does not remove immediately so the vector size wont change 
    }

m_entities 是一个处理从基类继承的派生对象的向量,循环简单地调用该向量中每个对象的Update() 函数。很简单,一切正常。

但是,当我决定调用 Add() 函数时,它只是将一个新对象添加到向量中,我得到了一个异常:

_Myval2 是 0xDDDDDDDD

我知道问题所在:我在派生类之一的Update() 函数内部调用Add() 函数,这会在仍在进行迭代的同时更改向量的大小。像这样:

for (auto &itr : m_entities) {
    itr.second->Update(l_time); //here is where I call "Add," changing the size of the vector  
    if (itr.second->m_isDead)   //and messing everything up
        Remove(itr.first);
}

所以我的问题是:如何添加到循环的向量 INSIDE 并且仍然能够完成循环而不会出错?

PS:我需要将它添加到循环中。如果我像使用Remove() 函数那样做,我想要的功能就不起作用。 Remove() 函数仅将实体的 ID 推送到向量中,该向量稍后将从向量中删除。是的,如果我用Add() 函数做类似的事情,它会起作用,但是只要我在循环中添加实体,我就想修改它:

if (sf::Mouse::isButtonPressed(sf::Mouse::Left)) {
    if (...) {
        ...

        //Here it will add to the vector and return the entity ID, which 
        //I use to find the entity and modify it right away
        unsigned int bulletId = m_entityMgr->Add(EntityType::Bullet);

        //just a pointer to the newly added entity so I can modify it
        Bullet *bullet = (Bullet*)m_entityMgr->Find(bulletId);

        ... //modifying entity
    }
}

然后在它退出这个Update()函数之后,它又回到那个循环并且因为向量的大小被修改而弹出错误。

【问题讨论】:

  • 在使用基于范围的for 时,您不能做任何改变容器中元素数量的事情。你invalidate the iterators它被用作簿记。有些容器比其他容器更宽容,但这是vector 不太友好的一种情况。
  • 有没有办法解决这个问题而不让它失效?
  • 你不能只存储Add/Find 产生的那些指针并在之后处理它们(就像你对Remove 所做的那样)?
  • 关于删除代码的战术说明:Look up std::remove_if。你应该能够让它为你工作。

标签: c++ loops vector containers sfml


【解决方案1】:

在基于范围的for 循环中,您无法执行任何修改容器大小的操作。在这种情况下,由于您只是添加元素,因此只需使用传统的基于索引的for 循环,例如:

for (size_t i = 0; i < m_entities.size(); ++i)
{
    auto &itr = m_entities[i];
    itr.second->Update(l_time); // may increase the size of the vector
    if (itr.second->m_isDead)
        Remove(itr.first);
}

或者,如果您不想在添加的新项目上致电 Update()

size_t size = m_entities.size();
for (size_t i = 0; i < size; ++i)
{
    auto &itr = m_entities[i];
    itr.second->Update(l_time); // may increase the size of the vector
    if (itr.second->m_isDead)
        Remove(itr.first);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-18
    • 2014-10-25
    相关资源
    最近更新 更多