迭代并移除Vector中的元素.错误:Vector迭代器不可递增



我正在尝试迭代存储的std::unique_ptr<Enemy> 's向量,以检查它们是否与player的攻击相碰撞。如果它们是,我想从向量中删除Enemy。然而,当我这样做时,我得到了错误:

File: c:program files (x86)microsoft visual studio 14.0vcincludevector线:102表达式:vector迭代器不可递增

代码如下:

if(actionCnt > 0)
{
    sf::FloatRect* playerAction = player->action(actionCnt);
    if (!enemies.empty()) {
        for (auto&i : enemies) {
            if (playerAction->intersects(i->getBox())) {
                i->kill();
                enemies.erase(std::remove(enemies.begin(), enemies.end(), i));
            }
        }
    }
    delete playerAction;
    playerAction = NULL;
}

所以从本质上来说,如果玩家触发了一次攻击,actionCnt就会变为1,这段就会被执行。

playerAction是一个被移动来模拟摆动的矩形,所以在这里我要检查矩形是否与敌人碰撞,如果发生碰撞会杀死它。

我使用的是SFML库,但是这些类的功能应该是显而易见的。

现在我只有一个敌人在战场上测试这个东西。所以当我点击它的时候,enemies向量应该是空的

代码中的auto将返回vector容器内部的类型。它不会给你迭代器。可以使用经典的for循环,并使用迭代器擦除元素,而不是基于范围的for循环。

if (!enemies.empty())
{
    for (auto itr = std::begin(enemies); itr!=std::end(enemies); ++itr)
    {
       if ((*itr)->hit)
       {
          (*itr)->kill();
          enemies.erase(itr);
       }
    }
}

或者您可以在std::remove_if中使用lambda函数,并在一行中完成整个操作。这实际上被称为擦除-删除习惯用法(更多信息在这里)。简而言之,remove_if以保留顺序的方式从lambda函数中移动(移动)容器中返回false的所有元素,并返回一个迭代器到最后一个元素的后面。从lambda函数返回true的元素被移动到vector的末尾,并且仍然是可解引用的,但未定义。要完全擦除元素,调用vector的erase函数删除容器逻辑端(从std::remove_if迭代器)到物理端(vector.end())的所有元素。

if (!enemies.empty())
   enemies.erase(std::remove_if(enemies.begin(),enemies.end(),[](const auto &itr){return itr->hit;}),std::end(enemies)); 

此外,当您希望对元素执行操作而不改变容器本身时,可以使用基于范围的for循环。为了获得更安全的代码,您可以使用while循环,而不是基于范围的For循环。

if (!enemies.empty())
{
    auto itr = std::begin(enemies); 
    while (itr != std::end(enemies) )
    {
        if ((*itr)->hit)
        {
           (*itr)->kill();
           enemies.erase(itr);
        }
        ++itr;
    } 
}

您可以在这里查看代码:http://rextester.com/EHLB11709我试着模仿你的游戏逻辑,只关注删除部分。从输出中,您将看到第6个元素已被删除。

此外,如果你想从矢量中删除所有内容,你应该使用clear() .

最新更新