c++ - unordered_map 删除段错误

标签 c++ segmentation-fault unordered-set

最近我发现 unordered_set 这种由 erase 方法引起的奇怪行为。我在下面展示了最小的例子。

首先我创建了一个 unordered_set。然后我删除其中一个元素,比如法国。然后我用 for 循环删除每个元素。执行后,它会出现段错误。但是,如果我注释掉删除法国部分,那么代码就可以正常工作。

这个程序是用 g++ test.cpp --std=c++11 编译的。 g++的版本是4.9.1。

#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;

}

有人知道吗?

谢谢, KC

最佳答案

删除基于范围的 for 循环中的元素是未定义的行为。当您删除集合中的一个元素时,该元素的迭代器将失效,并且在后台编译器使用当前元素的迭代器前进到下一个元素。基于范围的 for 等同于:

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); }

在 C++11 中,erase 方法返回一个新的迭代器,因此这避免了在它指向的元素被删除后递增旧迭代器。但也请注意,这段代码毫无意义,除非它只是一个实验。如果您只想清除集合的内容,请调用 myset.clear()

关于c++ - unordered_map 删除段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26833218/

相关文章:

c++ - 同时拥有复制构​​造函数和析构函数会导致段错误,但只有一个或另一个不会

c++ - 如何迭代 unordered_set 中的无序对?

c++ - c++ 和 boost 库的散列问题

c++ - 在其他窗口中使用 QApplication::activeWindow->winId() 时,QT 5.5 程序崩溃

C++ 从并发 vector 中删除元素

python - Homebrew 的 python gtk 导入导致段错误

c - "segmentation fault"将值分配给动态分配矩阵中的特定位置时

c++ - 返回指针的最佳方式

c++ - 删除后指针本身会发生什么?

c++ - 为 unordered_set 重载 () 运算符