编译环境:VS2015
语言:C++
参考博客:https://blog.csdn.net/qingtianweichong/article/details/9531919
话休絮烦,直接贴上报错图片:
看到list字样,应该是list容器部分出现了问题。下面贴出使用list容器的代码块:
1.错误源码
双向链表list及迭代器声明部分:
list<Bullet*> m_bullets;
m_bullets.clear();//使用clear可以清除掉链表的内容
list<Bullet*> ::iterator bp;//迭代器
遍历list链表
for (bp = m_bullets.begin(); bp != m_bullets.end(); bp++)
{
if (!((*bp)->IsDisappear()))
{
(*bp)->Display();//提领操作之后,提取的是指针变量
(*bp)->Move();
}
else
{
delete *bp;//删除这个指针指向的内存,迭代器还存在
m_bullets.erase(bp);
}
}
代码的主要目的是实现发射炮弹,当炮弹在显示区域时,进行显示和移动。当炮弹飞出屏幕外面时,进行炮弹的销毁:
一是通过删除指向炮弹内存的指针,用delete语句实现,二是清除掉指向该炮弹的迭代器,用erase()函数实现。
2.错误分析
乍一看,使用迭代器遍历链表 在逻辑上没什么问题啊。剩下的就是erase函数和list有关了。重新研究了erase()函数原理后,总结出以下重要三点:
- erase()函数用于在顺序型容器中删除迭代器p所指向的元素。
- 返回值是一个迭代器,且当前迭代器已经失效。
- 该迭代器指向被删除元素后面的元素。
对于第二点,是本错误的关键所在。即使erase函数有返回值,不用变量接受返回值也没关系。但是erase使用后必须用迭代器接受这个返回值,否则会产生出乎意料的结果。这样才能使遍历进行下去。
对于第三点,代码中for循环的最后还有 bp++ 迭代器自加的操作。也就是说删除一个节点后,迭代器已经指向了下一个要遍历的节点。执行bp++后,被删除节点的后一个节点会被跳过。那么被跳过的炮弹就不会在屏幕上Display和Move了。
3.修正
for (bp = m_bullets.begin(); bp != m_bullets.end(); )//去掉bp自加的操作
{
if (!((*bp)->IsDisappear()))
{
(*bp)->Display();
(*bp)->Move();
}
else
{
delete *bp;
bp = m_bullets.erase(bp);
//用当前迭代器接受erase返回的迭代器
continue;
//此时的迭代器已经移到下一位,跳过循环,不再执行下面的bp++;
}
bp++;
}
修改过后就不再报错了
欢迎在评论区补充留言~