列出迭代器不兼容

时间:2014-03-25 14:48:21

标签: c++ list iterator

当我逐步运行调试器运行程序时,我没有收到此错误。但是,当我实际运行该程序时,我每次都会得到它。它在这个循环中打破了:

auto ships = sprites.begin();
auto misscnt = sprites.begin(); misscnt++; misscnt++; //missiles start at the 3rd item on list every time.

while (misscnt != sprites.end())        //Missile Collision
    {
        ships = sprites.begin();
        ships++;
        if (dynamic_cast<Missile*>(*misscnt)->Collides((*ships)->GetLeft(), (*ships)->GetTop(), (*ships)->GetWidth(), (*ships)->GetHeight()) && dynamic_cast<Missile*>(*misscnt)->GetID() == "PlayerMiss")
        {
            ships--;

            (*ships)->AddToScore(10);
            sys->playSound(FMOD_CHANNEL_FREE, eHit, false, 0);
            while (true)
            {
                ships = sprites.begin();
                ships++;
                int x, y;
                x = rand() % Console::WindowWidth;
                y = rand() & Console::WindowHeight;
                if ((*ships)->GoodSpot(x, y, *(*--ships)))
                {
                    ships++;
                    (*ships)->SetLeft(x);
                    (*ships)->SetTop(y);
                    break;
                }
            }
            delete (*misscnt);
            sprites.erase(misscnt);
            ships = sprites.begin();
        }

        else if (dynamic_cast<Missile*>((*misscnt))->Collides((*ships)->GetLeft(), (*ships)->GetTop(), (*ships)->GetWidth(), (*ships)->GetHeight()) && dynamic_cast<Missile*>((*misscnt))->GetID() == "EnemyMiss")
        {
            (*ships)->SetLives((*ships)->GetLives() - 1);
            if ((*ships)->GetLives() > 1)
                sys->playSound(FMOD_CHANNEL_FREE, pHit, false, 0);
            if ((*ships)->GetLives() == 1)
                sys->playSound(FMOD_CHANNEL_FREE, LastLife, false, 0);
            if ((*ships)->GetLives() == 0)
            {
                bgmusic->setPaused(true);
                sys->playSound(FMOD_CHANNEL_FREE, pDie, false, 0);
                Sleep(4000);
                play = false;
                break;
                }
            while (true)
            {
                int x, y;
                x = rand() % Console::WindowWidth;
                y = rand() & Console::WindowHeight;
                if ((*ships)->GoodSpot(x, y, *(*++ships)))
                {
                    ships--;
                    (*ships)->SetLeft(x);
                    (*ships)->SetTop(y);
                    break;
                }
            }
            delete (*misscnt);
            sprites.erase(misscnt);
            ships = sprites.begin();
        }
        else
            misscnt++;
    }

程序永远不会进入if或else if物体,所以每当发射导弹时它都被添加到列表中。在环路中,如果导弹在任何情况下不发生碰撞,它应该增加误差并检查下一枚导弹(如果有的话)。

编辑:错误说

列出不兼容的迭代器 File :: F:\ VS2013 \ VC \ include \ list 行:289

我认为该行正在讨论文件“list”。

当它破坏时,VS指向while循环条件,表示它是下一行要执行的。

1 个答案:

答案 0 :(得分:2)

while()循环中有很多事情发生。它应该被重构,以便它无法通过无效迭代器获得这些问题。下面的代码尚未编译,但它将用于试图说明我的观点:

#include <algorithm>

bool IsAlive(ships& s)
{ return s.IsActive(); }

void DeleteMe(ship& s)
{  delete &s; }

//...
auto ships = sprites.begin();
auto misscnt = sprites.begin(); 
std::advance(misscnt, 2);

while (misscnt != sprites.end())        //Missile Collision
{
    // do the collision handling
    bool hasCollided = DoCollisionHandling( misscnt ); 
    if ( hasCollided )
       misscnt->setActive(false);
    ++misscnt;
}

// remove the inactive ones
list<sprites>::iterator pt = std::partition(sprites.begin(), sprites.end(), IsAlive); 
std::for_each(pt, sprites.end(), DeleteMe);
std::erase(pt, sprites.end());

根据您发布的内容,上面的代码应该是您尝试实现的内容的概要。请注意,唯一要做的就是调用DoCollisionHandling(它应该是一个虚函数,为每种类型重写),并返回是否发生了碰撞。 DoCollisionHandling()应该删除项目。

然后在while循环之外,我们将死的那些分区到分区的右边,这样我们就可以删除它们(或者稍后我们想做什么)。 &#34; pt&#34;是迭代器,它是活着的那些与死亡之间的分界线。

可能有更好的方法可以做到这一点,但我不推荐的一种方法是尝试在这样的循环中过于可爱,在这种情况下,你要删除被迭代的项目。除非是玩具或简单的循环,否则这样的事情似乎总是会引起麻烦。最好只标记项目,然后再处理它们。