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是在您刚刚擦除的同一迭代器上运行的,对于在容器中的更改之前获取的任何迭代器中的某些容器。