【问题标题】:vector iterator incrementable when erasing element of vector in 2 for loops在 2 个 for 循环中擦除矢量元素时矢量迭代器可递增
【发布时间】:2014-04-18 15:06:35
【问题描述】:

我目前正在为带有 2D 地图的控制台编写一个小游戏。我的游戏的 2 个元素是:摧毁田野和一个敌人,它以随机的方向传播(它越来越大)。这两个“实体”保存在一个包含两个向量(X 和 Y)的结构中。我现在正在尝试删除“_Enemy”的元素(

我尝试了很多不同的变体来做到这一点,而这种方法给我的错误最少的是这种方法(我已经在互联网上搜索了一段时间,但找不到我的问题的答案):

for (std::vector<int>::iterator itEX = _Enemys.X.begin(), itEY = _Enemys.Y.begin();
     itEX != _Enemys.X.end() && itEY != _Enemys.Y.end();
     ++itEX, ++itEY) {
  for (std::vector<int>::iterator itX = _DestroyedFields.X.begin(), 
                                      itY = _DestroyedFields.Y.begin(); 
           itX != _DestroyedFields.X.end() && itY != _DestroyedFields.Y.end(); 
           ++itX, ++itY) {
    if (*itY == *itEY && *itX == *itEX){
        itEY = _Enemys.Y.erase(itEY);
        itEX = _Enemys.X.erase(itEX);
    }
  }
}

PS:对不起,如果我的英语不是最好的,我是德国人^^

PSS:如果你想看我的整个代码,你可以在 Github 上找到它:https://github.com/Aemmel/ConsoleGame1

【问题讨论】:

  • 目前,您在执行erase...时会增加迭代器...
  • 我建议使用一个简单的结构来定位。
  • @Jarod42 简单结构是什么意思?
  • 正在使用哪个双循环实现? git 上的版本假定 X 和 Y 总是相同的大小。以上应该是搜索正确元素的更好方法。
  • @CPlusPlusOOAandD 哎呀,没注意到它不一样^^。使用上面的例子。

标签: c++ vector stl iterator erase


【解决方案1】:

使用迭代器it 擦除后,您不能再使用it,因为it 已失效。您应该使用一个新的、有效的迭代器来擦除的调用结果。

for( it = v.begin(); it != v.end();)
{
   //...   
   if(...)
   {
      it = v.erase( it); 
   }
   else
   {
      ++it;
   }
   ...
}

【讨论】:

  • 不起作用,它给出了错误:“vector iterator not dereferencable”
  • 用你的方法代替我的方法和 _Enemys(所以 itEX 和 itEY)。而且我认为它总是在 if 语句中崩溃(我在擦除时打印出来,在 else 语句中,当条件为真时,它在 if 语句之后停止打印)
【解决方案2】:

我首先修复了这个错误:创建一个“简单结构”(struct Entity{int X; intY} 然后是 std::vector [在此处插入名称]),然后添加一个中断;如果条件为真。

for (Uint itE = 0; itE < _Enemys.size(); ++itE){
        for (Uint it = 0; it<_DestroyedFields.size(); ++it){
            if (_Enemys.at(itE).Y == _DestroyedFields.at(it).Y 
                && _Enemys.at(itE).X == _DestroyedFields.at(it).X){
                _Enemys.erase(_Enemys.begin()+itE);
                break;
            }
        }
    }

【讨论】:

  • 如果你加上bool operator == (const Position&amp; lhs, const Position&amp; rhs) { return lhs.x == rhs.x &amp;&amp; lhs.y == rhs.y; },那么你可以写条件:_Enemys.at(itE) == _DestroyedFields.at(it)(或[]_Enemys[itE] == _DestroyedFields[it]
  • 顺便说一句,你擦除时仍然增加itE,所以你可能会错过删除连续元素。
【解决方案3】:

struct Position {int x; int y;}; 和一些实用程序运算符,
您可以执行以下操作之一:(https://ideone.com/0aiih0)

void filter(std::vector<Position>& positions, const std::vector<Position>& destroyedFields)
{
    for (std::vector<Position>::iterator it = positions.begin(); it != positions.end(); ) {
        if (std::find(destroyedFields.begin(), destroyedFields.end(), *it) != destroyedFields.end()) {
            it = positions.erase(it);
        } else {
            ++it;
        }
    }
}

或者,如果输入已排序,您可以使用“差异”:

std::vector<Position> filter2(const std::vector<Position>& positions, const std::vector<Position>& destroyedFields)
{
    std::vector<Position> res;
    std::set_difference(positions.begin(), positions.end(),
                        destroyedFields.begin(), destroyedFields.end(),
                        std::back_inserter(res));
    return res;
}

【讨论】:

    猜你喜欢
    • 2020-11-28
    • 1970-01-01
    • 1970-01-01
    • 2020-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-29
    • 1970-01-01
    相关资源
    最近更新 更多