无序映射擦除segfault
unordered_map erase segfault
最近我发现了由erase
方法引起的无序集的这种奇怪行为。我在下面举一个最简单的例子。
首先,我创建了一个无序集。然后我抹掉其中一个元素,比如法国。然后我用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循环内的元素是未定义的行为。当您擦除集合中的一个元素时,该元素的迭代器将无效,编译器在后台使用当前元素的迭代器前进到下一个元素。基于的范围相当于:
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()
。
相关文章:
- 引用一个已擦除类型(void*)的指针
- 擦除while循环中迭代的元素
- 在运行时处理类型擦除的数据-如何不重新发明轮子
- C++擦除(如果存在)
- 在映射擦除c++期间执行循环的次数
- 为什么擦除方法会影响结束方法
- C++ 字符串类擦除成员函数的时空复杂性
- 类型擦除的std::function与虚拟函数调用的开销
- C++14 中unordered_map矢量和擦除删除成语的奇怪行为
- C++ 擦除函数中需要澄清
- 循环挂起迭代的 std::擦除 on std::list
- 擦除许多矢量元素,同时使用'auto'
- 如何擦除冗余输入?
- C++ STL 设置按值擦除
- 如何在C++中允许成员函数的自定义返回类型进行类型擦除?
- 为什么我的向量::擦除调用会抛出"vector subscript out of range"?
- 如何在写入文件时擦除最后一个逗号
- C++:std::ofstream 方法 open() 在第二次迭代时擦除打开的 ifstream 文件
- 在嵌套循环中从矢量擦除时,segfault
- 无序映射擦除segfault