C++ - 矢量迭代器 + 偏移超出范围

C++ - Vector iterator + offset out of range

本文关键字:范围 迭代器 C++      更新时间:2023-10-16

我已经查看了大约 10 个关于同一消息的答案,但尚未找到我的问题。

在 level.h 中 Level 类中:

std::vector<Bomb> m_bombs;

在级别.cpp:

添加炸弹:

Bomb bomb;
bomb.owner = player;
bomb.power = power;
bomb.x = pos.x;
bomb.y = pos.y;
bomb.timer = 3.0f;
m_bombs.push_back(bomb);

检查炸弹(每帧):

void Level::updateBombs(float dt)
{
    for(int i = 0; i < m_bombs.size(); i++)
    {
        m_bombs[i].timer -= dt;
        if(m_bombs[i].timer <= 0)
            m_bombs.erase(m_bombs.begin() + i);
    }
}

我 100% 确定程序在调用擦除函数的行上崩溃。我能够从向量输出信息,这使得这种方式更加混乱。炸弹正确位于矢量中。如果我m_bombs.remove_last()这样做,它会删除向量中的最后一个元素。似乎只是在擦除和开始()方面存在问题。

您可以使用 erase-remove-idiom 来修复代码。

m_bombs.erase(std::remove_if(m_bombs.begin(), m_bombs.end(), 
                             [](const Bomb& b){ return b.timer < 0.0f;}), 
                             m_bombs.end());

最好updateBombs函数拆分为两个函数:

updateBombs() does bomb timer update only
removeBombs() removes bombs which expired

也许您可以尝试向后擦除矢量,例如,如果要擦除炸弹索引 3 和 5,则删除索引为 5 然后是 3 的那个,因为如果您从 0N-1 按顺序擦除,当您擦除索引 3 时,索引 5 将成为索引 4,这可能会导致在到达循环的最后一步时超出界限。

试试这个:

int pivot = 0
void Level::updateBombs(float dt)
{
    for(int i = 0; i < m_bombs.size(); i++)
    {
        m_bombs[i].timer -= dt;
        if(m_bombs[i].timer <= 0)
        {
            m_bombs.erase(m_bombs.begin() + i - pivot);
            pivot++;
        }
    }
}

我在清除或创建向量时遇到了类似的问题。出现此问题的原因是在运行时使用了 2 个不同版本的 dll。清除和创建是在调用 Open CV 函数时发生的,这些函数似乎使用与我的视觉工作室不同的运行时库。更改Visual Studio最终解决了这个问题(在更改Visual Studio之前,我尝试了很多旧的OpenCV构建,但无济于事)。VS 2008 和 2013 不起作用,VS2010 起作用了。

我会用你自己的int变量替换m_bombs.size(),你在移除炸弹后递减。我个人在.size()方面遇到了问题.它应该返回向量中的元素数量,但我有一个空向量,.size()返回大于零的数字。 也许尝试这样做将有助于缩小您的问题范围。