按位置删除向量中的元素?

Delete elements in vector by position?

在我的 class 中,我试图使用 for 循环从 std::vector 中删除一个元素。但是,当我尝试删除该元素时,我收到一个错误消息,我不太确定如何解决它。我得到的错误是:

Error 4 error C2679: binary '+' : no operator found which takes a right-hand operand of type 'Enemy *' (or there is no acceptable conversion)

void Enemy::UpdateEnemies(SDL_Renderer * render)
{
    for (int i = enemies.size() - 1; i >= 0; i--)
    {
        enemies[i]->Update();
        if (enemies[i]->Active == false)
        {
            // Receive the error here
            enemies.erase(enemies.begin() + enemies.at(i));             
        }
    }
    if ((SDL_GetTicks()-prevSpawnTime)/1000.0f > enemySpawnTime)
    {
        prevSpawnTime = SDL_GetTicks();
        //Add an anemy
        AddEnemy(render);
    }    
}

假设你想删除第i个元素,你需要做

enemies.erase(enemies.begin() + i);

或更好

enemies.erase(std::next(enemies.begin(), i));

在您的情况下 enemies.at(i) returns 位置 i 处的取消引用迭代器,即 Enemy 类型的元素,而不是 i 或迭代器位置 i.

更好的方法是使用反向迭代器:

for(auto it = enemies.rbegin(); it != enemies.rend(); ++it)
{
    (*it)->Update();
    if ((*it)->Active == false)
    {   // need `base()` to convert to regular iterator, then substract 1
        enemies.erase(std::prev(it.base())); // remove the current position
        /* or, equivalently
        enemies.erase(std::next(it).base()); 
        */
    }
}

这一行:

enemies.erase(enemies.begin() + enemies.at(i));
  • enemise.at(i) returns 存储在向量中的敌人。
  • enemies.begin() 是一个指针

如错误所述,您正在尝试添加指针和向量。

您可能只想致电:

enemies.erase(enemies.begin() + i);

其他答案为您提供了天真的解决方案。但是,如果要移除的敌人不止一个,则需要更好的解决方案。

在这种情况下,使用 <algorithm> 中的 std::remove_if 会更好。这将避免重复洗牌向量中的项目。它的工作原理是将您要删除的所有内容移动到容器的 end,然后为您提供一个指向这些内容开头的迭代器。

auto removed_iter = std::remove_if( enemies.begin(), enemies.end(),
                                    []( const Enemy * e ) { return e->IsActive(); } );

enemies.erase( removed_iter, enemies.end() );

在这种情况下,您必须先更新所有敌人。如果不需要按相反的顺序进行,则:

for( auto e : enemies ) e->Update();

除了其他人所说的之外,我会更进一步并建议从循环内的向量中擦除可能会导致未定义的行为。我没有看到中断,所以我假设可能有多个不活跃的敌人。与其编写自己的循环,不如考虑使用 std::remove_if 算法。本质上,您的代码是尝试添加一个带有对象引用的迭代器,该引用将无法编译。 remove_if 解决方案基本上会将所有 Active==false 的敌人复制到容器的末尾,同时将其他所有内容向前移动。它提供了一种方便的方法来首先识别要删除的内容,然后一次将它们全部删除。此外,如果您没有 C++11 编译器,那么如果您使用不同类型的谓词,同样的事情也会起作用。 remove_if link 包含函数示例,但您也可以使用函子。

enemies.erase(std::remove_if(enemies.begin(), enemies.end(), [](const Enemy* e){ return e->Active == false; }), enemies.end());

有关更多信息,请查看这些内容。

What is a lambda expression in C++11?

http://www.cplusplus.com/reference/algorithm/remove_if/

C++ Functors - and their uses