C++ 在映射上迭代并擦除元素

C++ 在映射上迭代并擦除元素,c++,c++11,std,C++,C++11,Std,我有一个全局变量作为map和一个函数,该函数迭代该map的元素,例如: void printMap(){ for ( auto it = MyMap.begin(); it != MyMap.end(); ++it ){ std::cout << it->second; } } 但是,通过添加擦除行,我得到了这种类型的异常错误: 线程2:EXC\u错误访问(代码=1,地址=0x2000002) 我试过另一种方法,是这样的: void myFu

我有一个全局变量作为
map
和一个函数,该函数迭代该
map
的元素,例如:

void printMap(){
    for ( auto it = MyMap.begin(); it != MyMap.end(); ++it  ){
        std::cout << it->second;
    }
}
但是,通过添加擦除行,我得到了这种类型的异常错误:

线程2:EXC\u错误访问(代码=1,地址=0x2000002)

我试过另一种方法,是这样的:

void myFunction(){
    printMap(); 
    MyMap.clear();
}
但我也有同样的例外

线程2:EXC\u错误访问(代码=1,地址=0x0)

据我所知,当我们引用一个不存在的内存位置时,就会发生这种异常。但我知道它在那里,因为迭代器得到了它的值,并且它被打印出来了。即使如此,我还是使用了第二种方法,以防我没有引用不存在的内存位置,但仍然得到了异常

那么,我如何迭代元素,打印结果,然后删除它呢

更新1
根据以下建议和链接主题,我将我的功能更改为:

void printMap(){
    bool i = true;
    for (auto it = MyMap.cbegin(), next_it = MyMap.cbegin(); it != MyMap.cend(); it = next_it)
    {
        cout << it->second;
        next_it = it; ++next_it;
        if (i) {
            MyMap.erase(it);
        }

    }
}
void printMap(){
bool i=真;
for(auto it=MyMap.cbegin(),next_it=MyMap.cbegin();it!=MyMap.cend();it=next_it)
{
第二;
next_it=it;++next_it;
如果(i){
我的地图。删除(它);
}
}
}
我也试过这个和这个

问题仍然没有解决,我得到了同样的错误




更新2
我在另一台机器上运行相同的代码,效果很好。我仍然不知道原因是什么,所以我想正如评论中所建议的那样,
std::map
首先出现了一些问题


另外,第一台机器是mac,第二台是Linux。当您从映射中删除元素时,您已使循环中使用的迭代器无效,从而导致错误。由于这个原因,erase方法返回一个迭代器

for( auto it = MyMap.begin(); it != MyMap.end(); )
{
    std::cout << it->second;
    it = MyMap.erase(it);
}
for(auto-it=MyMap.begin();it!=MyMap.end();)
{
std::cout秒;
it=MyMap.erase(它);
}
这的确是一个重复的问题。你只是没有很好地理解它,以至于看不出它是一个复制品。我希望关于使迭代器无效的解释有助于澄清问题。

在C++11及更高版本中,将迭代器
返回到被擦除的元素后面的元素。由于您使用的是
auto
,因此您使用的是C++11或更高版本,因此在通过
std::map
循环进行擦除时可以使用新的迭代器,例如:

void printMap(){
    auto it = MyMap.cbegin();
    while (it != MyMap.cend()) {
        std::cout << it->second;
        it = MyMap.erase(it);
    }
}

可能的重复我认为问题有点不同,我得到一个例外,引用一个现有的内存位置,好像它不存在。看看它不存在,因为你刚刚释放了它,因此你不允许访问它@em2er的副本比我的好一点:)您的
地图中包含哪些类型?你确定他们的析构函数不是导致错误的原因吗?当我尝试这个时,我得到了这个错误:线程1信号sigabrt。我遵从了它,然后再次运行,我得到了旧的错误。线程1信号中止很可能意味着线程中发生了未处理的异常,可能是完全无关的。这就是为什么将您要问的问题缩小到尽可能最简单的测试用例中,并将代码与问题一起发布是很重要的。如果您创建一个新的控制台应用程序,创建一个std::map,用元素填充它,然后使用给定的循环进行擦除,并且应用程序中没有其他代码,那么您将看到它如何在没有错误的情况下擦除。至于其他错误,我们不知道,因为我们无法想象代码中有什么没有发布或调试。要调试未处理的异常,您可以尝试在Visual Studio的“异常”对话框中启用“中断”异常,如果您使用的是IDE。看,我使用了这个代码作为精确的,我仍然得到相同的错误然后,我猜你可能是迭代一个损坏的
std::map
。你试过上面描述的其他成语吗?它们是否表现出相同的错误?那么您的
std::map
很可能已损坏,因为这些已被证明的习惯用法在正常条件下都能工作。似乎是这样。有没有其他有效的性能和内存方面的地图选择?@user7631183我想你没有领会我的意思。很明显,您操作的是无效的
std::map
,您需要找出原因并修复它,而不是尝试解决它。
void printMap(){
    auto it = MyMap.cbegin();
    while (it != MyMap.cend()) {
        std::cout << it->second;
        it = MyMap.erase(it);
    }
}
void printMap(){
    for ( auto &it: MyMap ){
        std::cout << it.second;
    }
}