迭代和删除Vector中的元素。错误:矢量迭代器不可增量

时间:2016-11-12 18:13:46

标签: c++ vector sfml

我试图迭代存储的std::unique_ptr<Enemy>的向量,以检查它们是否与player的攻击发生冲突。如果是,我想从向量中删除Enemy。 但是,当我这样做时,我收到错误:

文件:c:\ program files(x86)\ microsoft visual studio 14.0 \ vc \ include \ vector 行:102 表达式:向量迭代器不可递增

以下是代码:

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库,但应该明白这些类的功能。

现在我只有1名敌人在场上测试这些东西。所以当我点击它时,enemies向量应为空。

1 个答案:

答案 0 :(得分:3)

代码中的auto将返回向量容器中的类型。它不会给你迭代器。您可以使用经典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函数并在一行中完成整个操作。这实际上被称为擦除 - 删除习语(更多here)。简而言之,remove_if以保留顺序的方式移动(移动)容器中从lambda函数返回false的所有元素,并将迭代器返回到最后一个元素之后的迭代器。从lambda函数返回true的元素将移动到向量的末尾,但仍然是不可引用的,但尚未定义。要完全擦除元素,将调用向量的擦除函数以从逻辑端(迭代器从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()