【问题标题】:How do I prevent a segmentation fault from occuring when an object in a vector is erased while in a for loop?在 for 循环中擦除向量中的对象时,如何防止发生分段错误?
【发布时间】:2012-01-07 01:44:30
【问题描述】:

[编辑 2] 这可能是因为表面正在被释放,而其他对象仍在使用它......所以我想写它,所以只有当屏幕上没有更多对象时它才会被释放。

[编辑][更新] 我修复了使用迭代器的代码,但我仍然遇到同样的问题......我刚刚确认这是对象的析构函数的问题。在类中,析构函数调用 SDL_FreeSurface(image);从内存中释放对象的图像...但是使用复制构造函数创建的对象显然不能这样做。我需要做什么才能使其与使用复制构造函数创建的对象正常工作?我似乎在 Google 上找不到与此相关的任何内容。

数字是指给定时间屏幕上的子弹数...我有一个对象“子弹”的向量(向量子弹;)...代码检查触发按钮(z)是否按下,并在向量中添加一个新项目符号(如果是)。然后它更新(移动,blits),然后检查子弹是否在屏幕的末端......一切正常,直到子弹到达应该被摧毁的屏幕末端。

if (trigger)
{
  bullet.push_back(Bullet(position.x, position.y));
  ++number;
}

for(int i = 0; i < bullet.size(); i++)
{
  bullet[i].update();
}

问题出在下面...当删除项目符号对象时,程序会因分段错误而退出...现在,我明白为什么会发生这种情况,因为矢量大小在循环中发生了变化,但是我不知道如何解决它......我添加了休息,认为它可以解决问题,因为无论如何在给定时间只有一个子弹可以

for(int i = 0; i < bullet.size(); i++)  
{
  if (bullet[i].position.y <= 0)
  {     
    bullet.erase(bullet.begin() + i);
    --number;
    break;
  }
}

我是向量的新手,所以如果我有不明白的地方或者我犯了 n00b 错误,请多多包涵。

【问题讨论】:

  • 您的代码中的问题是i 的含义在erase 之后发生了变化。您有一个函数假设向量的对象位置在函数的生命周期内是恒定的,该函数调用一个改变这些位置的函数。
  • 关于您的编辑和复制构造函数,请阅读C++ FAQ: What is the Rule of Three?
  • 谢谢...帮助了。

标签: c++ oop vector for-loop


【解决方案1】:

序列容器的标准擦除循环如下所示:

for (std::vector<Bullet>::iterator it = v.begin(); it != v.end() /* not hoisted */; /* no increment */)
{
    if (delete_condition)
    {
        it = v.erase(it);
    }
    else
    {
        ++it;
    }
}

使用迭代器比使用计数索引更可取,因为它将您的代码从计数器算术中解放出来,这不会增加代码的清晰度并且相当麻烦,而这里介绍的迭代器版本是相当自我的-解释性的。

关键是在出现erase 时不要增加循环变量。

您可能还想查看remove/erase 成语:

v.erase(std::remove_if(v.begin(), v.end(),
                       [](Bullet & b) -> bool { return delete_condition }),
        v.end());

【讨论】:

  • 提供 C++11 唯一答案恕我直言还为时过早 -
  • @AdrianCornish:lambda 被简单地转换为拼写函数/函子,auto 也被拼写类型名称替换。这些实际上只是印刷速记。你会感激我没有说auto it(std::begin(v)) ;-)
  • 当你拥有标准并且已经编程多年时,这是微不足道的 :-) 就像我说的恕我直言
  • 我可以用什么代替 auto?我正在编译似乎基于此的问题...我收到“错误:无法将 '__gnu_cxx::__normal_iterator > >' 转换为'int' 在初始化”。
  • GCC 和 MSVC 都已经支持 lambdas 和 auto。只有 clang 仍然不支持 lambdas :(
猜你喜欢
  • 1970-01-01
  • 2017-04-17
  • 2019-10-09
  • 1970-01-01
  • 1970-01-01
  • 2020-08-22
  • 2017-05-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多