如下unordered_set的erase操作导致程序崩溃,crash。
#include <iostream>
 #include <string>
 #include <unordered_set>
int main ()
 {
   std::unordered_set<std::string> myset =
   {"USA","Canada","France","UK","Japan","Germany","Italy"};
  // erasing by key, causing segfault later; no segfault if commented out
   myset.erase ( "France" );                         
  std::cout << "myset contains:";
   for ( const std::string& x: myset ) { myset.erase(x); }
  // The problem persists for a regular for loop as well. 
   //for (  std::unordered_set<std::string>::iterator it = myset.begin(); it!=myset.end(); it++  ) { myset.erase(it); }
std::cout << std::endl;
return 0;
}
原理分析:
用循环的方法删除内置范围的元素,这种做法是未定义的,也就是说产生未知的操作。
当你删除一个元素的时候,迭代器指向的元素已经被释放内存值,已经无效了,在这种情况下,编译器把当前的迭代器指向下一个元素,类似如下代码:
auto && __range = range-init;
 for ( auto __begin = begin-expr(__range),
    __end = end-expr(__range);
    __begin != __end;
    ++__begin ) {
    for-range-declaration = *__begin;
    statement
 }
这个时候 ++__begin 被调用,元素被删除,迭代器是无效的。
正确的删除方法之一:
auto it = myset.begin();
 while (it != myset.end()) { it = myset.erase(it); }
In C++11 erase方法返回新的指针 指向下一个有效的元素,避免在原来失效的迭代器上做增长。但是这里还有一点是,要想彻底清除内存值,需要调用clear函数。