Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ms-access/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 更新地图值_C++ - Fatal编程技术网

C++ 更新地图值

C++ 更新地图值,c++,C++,我有一张这样的地图: map<prmNode,vector<prmEdge>,prmNodeComparator> nodo2archi; map nodo2arch; 当我必须更新值(向量)时,我取键和他的值,更新值的向量,擦除旧键和值,然后插入键和新向量。代码如下: bool prmPlanner::insert_edgemap(int from,int to) { prmEdge e; e.setFrom(from); e.setTo(to);

我有一张这样的地图:

map<prmNode,vector<prmEdge>,prmNodeComparator> nodo2archi;
map nodo2arch;
当我必须更新值(向量)时,我取键和他的值,更新值的向量,擦除旧键和值,然后插入键和新向量。代码如下:

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;
}
bool prmPlanner::insert_edgemap(int-from,int-to){
prmEdge;
e、 setFrom(from);
e、 setTo(to);
对它进行迭代器;
for(it=nodo2archi.begin();it!=nodo2archi.end();it++){
向量appo;
prmnoden;
n=(*it)。首先;
int indice=n.getIndex();
如果(指数=f | |指数=t){
约为clear();
向量机;
依丹佛奇=(*it)。第二;
appo=(i);
近似推回(e);
nodo2archi.erase(它);
nodo2archi.insert(配对(n,appo));
}
}
返回true;
}
问题是,在最初的40-50次迭代中,一切都很顺利,地图更新得很好,而随着迭代次数的增加,地图有时会出现分段错误,有时会出现无限空闲。我不知道为什么。有人能帮我吗??
非常感谢。

Yo请在迭代集合时修改它。

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

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

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

问题是,在删除迭代器
后,您试图对其执行操作(增量),这是一种未定义的行为。一些答案指出,在遍历容器时修改容器是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)是无效的,因此对于这个问题没有单一的解决方案,您必须知道您在迭代什么。至少在下一个标准发布和编译器赶上之前。

您只是想将数据附加到一些映射向量吗?在这种情况下,不需要擦除和插入任何内容:

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

如果做得正确就不会。对于序列容器,
erase
操作将有效迭代器返回到容器中的下一个元素。这是关联容器中缺少的,但将在下一个标准中添加。UB是在您刚刚擦除的同一迭代器上运行的,对于在容器中的更改之前获取的任何迭代器中的某些容器。