更新地图值

时间:2010-02-03 12:25:20

标签: c++

我有这样的地图:

map<prmNode,vector<prmEdge>,prmNodeComparator> nodo2archi;

当我必须更新值(向量)时,我取出键和他的值,我更新值的向量,我擦除旧键和值然后我插入键和新向量。代码是这样的:

bool prmPlanner::insert_edgemap(int from,int to) {

  prmEdge e;
  e.setFrom(from);
  e.setTo(to);

  map<prmNode,vector<prmEdge> >::iterator it;

  for (it=nodo2archi.begin(); it!=nodo2archi.end(); it++){
      vector<prmEdge> appo;
      prmNode n;
      n=(*it).first;
      int indice=n.getIndex();

      if (indice==f || indice==t){
          appo.clear();
          vector<prmEdge> incArchi;
          incArchi=(*it).second;
          appo=(incArchi);

          appo.push_back(e);

          nodo2archi.erase(it);
          nodo2archi.insert(make_pair(n,appo) );
       }

    }
return true;
}

问题在于,对于前40-50次迭代,所有内容都会变得更好,并且地图会更新,而有了更多的迭代,有时会出现分段错误,有时会出现无限空闲。我不知道为什么。有人可以帮我吗? 非常感谢你。

6 个答案:

答案 0 :(得分:4)

您正在迭代nodo2archi,同时通过nodo2archi.erase(it);nodo2archi.insert(make_pair(n,appo) );更改其大小。如果你这样做,你的迭代器可能会变得无效,你的it++可能会崩溃。

答案 1 :(得分:2)

问题是在擦除迭代器it之后,你试图对它执行操作(增量),这是未定义的行为。一些答案声明在迭代时修改容器是UB,这不是真的,但你必须知道迭代器何时失效。

对于序列容器,erase操作会将新的有效迭代器返回到容器中的下一个元素,因此这将是从这样的容器中擦除的正确且惯用的方法:

for ( SequenceContainer::iterator it = c.begin(); it != c.end(); ) 
   // note: no iterator increment here
   // note: no caching of the end iterator
{
   if ( condition(*it) ) {
      it = c.erase(it); 
   } else {
      ++it;
   }
}

但遗憾的是,在当前标准中,关联容器erase不返回迭代器(这在新标准草案中已修复),因此您必须手动伪造它

for ( AssociativeContainer::iterator it = c.begin(); it != c.end(); )
   // again, no increment in the loop and no caching of the end iterator
{
   if ( condition(*it) ) {
      AssociativeContainer::iterator del = it++; // increment while still valid
      c.erase(del);                              // erase previous position
   } else {
      ++it;
   }
}

更令人遗憾的是,第二种方法,对于关联容器是正确的,对某些序列容器(特别是std :: vector)无效,因此没有单一的解决方案来解决问题,你必须知道你在迭代什么过度。至少在出版下一个标准并且编制者赶上之前。

答案 2 :(得分:2)

您是否只是尝试将数据附加到某些映射的向量中?在这种情况下,您不需要删除和插入任何内容:

for (MapType::iterator it = map.begin(); it != map.end(); ++it) {
    if (some_condition) {
        it->second.push_back(some_value);
    }
}

答案 3 :(得分:1)

Yo 在迭代时修改集合。

答案 4 :(得分:0)

在迭代地图时,您正在擦除节点。这是在寻找麻烦:)

答案 5 :(得分:0)

迭代时,不得修改集合本身。 C ++会允许它,但它仍会导致未定义的行为。其他语言(如Java)具有快速失败的迭代器,它们在修改集合时会立即中断。