【问题标题】:Strange problem while iterating on a map after erasing in c++在 C++ 中擦除后在地图上迭代时出现奇怪的问题
【发布时间】:2020-03-12 10:49:25
【问题描述】:

我有一个包含我所有图块的图块地图。我想擦除一个图块并同时继续绘制我的图块。

问题是,在我擦除了一个图块(如索引 = 2)后,第一次完整的图块绘制迭代是正确的(绘制 0、1、3、4、...),但第二个导致崩溃,因为它尝试绘制所有图块 (0,1,2,3,...)

这是我擦除一块瓷砖的代码

auto it = tiles.begin();
while(it != tiles.end()){
    if(it->first == i){
        it = tiles.erase(it);
    }
    else
        ++it;
}

这是我要绘制的代码

for(auto& itr : tiles){
    if(itr.first == limit)
        break;
    if(itr.first < 10){
        cout<<"draw : "<<itr.first<<"\t"<<itr.second.str()<<endl;
    }
    itr.second.draw(window,dt);
}

(限制是不要遍历 x 数千个图块)

这里是控制台输出

平局:0 (0,24) 停留 平局 : 1 (32,24) 停留 平局 : 2 (64,24) 停留 平局 : 3 (96,24) 停留 平局 : 4 (128,24) 停留 平局 : 5 (160,24) 停留 平局 : 6 (192,24) 停留 平局 : 7 (224,24) 停留 平局 : 8 (256,24) 停留 平局:9(288,24)停留

删除 0 : 0 (0,24) 停留 1 (32,24) 人入住

平局:1 (32,24) 停留 平局 : 2 (64,24) 停留 平局 : 3 (96,24) 停留 平局 : 4 (128,24) 停留 平局 : 5 (160,24) 停留 平局 : 6 (192,24) 停留 平局 : 7 (224,24) 停留 平局 : 8 (256,24) 停留 平局:9(288,24)停留

绘制:0 (-1163005939,-1163005939)

对不起我的英语,谢谢你的帮助。

【问题讨论】:

  • 为什么不tiles.erase(tiles.find(i))
  • 您的代码中某处存在错误。错误可以在任何地方。显示的代码中没有任何内容表明错误是什么;因此,您必须显示 minimal reproducible example,否则 stackoverflow.com 上的任何人都不太可能为您提供帮助。有关详细信息,请参阅How to Ask
  • 句中and continue draw in the same time,你的意思是来自另一个线程吗?如果是这样,当另一个线程迭代它时,您不能从一个线程修改映射。如果你想这样做,你必须使用锁(例如std::mutex)。

标签: c++ dictionary iterator erase


【解决方案1】:

我认为最有可能的是,您实际上并没有从您正在绘制的图块地图中删除该元素。你如何将地图传递给删除瓷砖的代码?您可能正在某处创建副本。

仅供参考,这样的代码可以工作,所以你的代码没有明显的错误。该错误位于您发布的代码之外的某个位置。

int main() {
  std::map<int, std::string> m = {{0, "A"}, {1, "B"}, {2, "C"}};

  for (auto& t : m) {
    std::cout << t.first << " = " << t.second << std::endl;
  }

  auto it = m.begin();
  while (it != m.end()) {
    if (it->first == 1) {
      it = m.erase(it);
    } else {
      ++it;
    }
  }

  for (auto& t : m) {
    std::cout << t.first << " = " << t.second << std::endl;
  }

  return 0;
}

【讨论】:

  • 没有创建副本,我已经测试了复制构造函数和运算符 =。此外,主循环内的代码(矿工是我的播放器,更新负责碰撞、移动和删除)miner.update(time); tileMap.printTiles(); tileMap.draw(窗口,时间,sf::Vector2f(miner.getX(),miner.getY()));在控制台中给我完全相同(第一次迭代正常,第二次迭代崩溃)要知道的另一件事是,在此错误之前,我使用的是向量并且一切正常。但是,对于擦除期间的性能问题,我将矢量修改为地图
  • 您能否发布一个包含所有导致问题的代码的最小示例?显然,您不仅仅是擦除并绘制图块,因为这样会起作用。
【解决方案2】:

擦除迭代值时,迭代不能指向下一个,所以简单的方法是:

  auto it = m.begin();
  while (it != m.end()) 
  {
    if (it->first == 1)
      m.erase(it++); // After return from erase function, it point to next pointer.
    else
      ++it;
  }

【讨论】:

    猜你喜欢
    • 2013-04-17
    • 2017-02-24
    • 2011-05-11
    • 2011-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-23
    相关资源
    最近更新 更多