迭代时擦除设置元素///
erase set element while iterating///
我不明白,为什么是运行时错误? 迭代时擦除设置元素。
set<int> sset;
sset.insert(3);
sset.insert(5);
sset.insert(6);
for(auto s: sset){
sset.erase(s);
}
所以只是为了进一步解释,
你实际上写的是:
for (set<int>::const_iterator i=sset.begin(), e=sset.end(); i != e; i++)
{
auto s = *i;
sset.erase(s);
}
所以问题是在进行擦除时,内部迭代器i
失效。这是尝试按顺序删除许多容器的内容的普遍痛苦。
出于同样的原因,以下更传统的顺序删除代码也很糟糕,但也许更明显:
for (set<int>::iterator i=sset.begin(), e=sset.end(); i != e; i++)
{
sset.erase(i);
}
修复:
通常,当可以执行以下操作时,依赖整个容器的上下文交换销毁会更简单:
C++98: SsetType().swap(sset);
C++11: sset = decltype<sset>();
你可以做的是:
sset.erase(sset.begin(), sset.end());
解决此问题的另一种方法是继续删除begin()
,直到empty()
集
但所有这些的问题在于,您无法轻松扩展它们以有条件地擦除正在迭代的集合的成员。是的,也有条件擦除的帮助程序,它们可以与 lambda 一起使用,因此它们可以携带状态,但它们通常与滚动自己的循环一样难以使用。
从 c++11 开始,set::erase(iterator( 返回一个新的迭代器,可以安全地继续迭代,所以你可以编写:
for (set<int>::iterator i=sset.begin(), e=sset.end(); i != e; )
{
i = sset.erase(i);
}
如果您正在执行一些条件测试,则:
for (set<int>::iterator i=sset.begin(), e=sset.end(); i != e; )
{
if ( ... condition ... )
i = sset.erase(i);
else
i++;
}
以前,在 C++98 中,你会写这样的东西:
for (set<int>::iterator i=sset.begin(), e=sset.end(); i != e; )
{
auto j = i;
j++;
if ( ... condition ... )
i = sset.erase(i);
i = j;
}
作为练习,您可以将j
的使用滚动到for
语句中。 不过,在 C98 中获取初始 j++ 是很棘手的!
遗憾的是,从sset
中删除元素将使容器上的隐式迭代无效; 这是由漂亮的语法糖auto s : sset
使用的。
这是未定义的行为。
相关文章:
- 在QComboBox或QListWidget中设置所选元素的样式文本?
- 如果我在相应 char 数组的声明中为其提供额外的元素,是否会自动设置 NULL?
- 无法在构造函数中执行设置元素插入
- 循环中的变量被设置为下一个数组的元素始终具有相同的内存地址?
- 为 unordered_map 中的元素设置默认构造函数(如果是 [] 运算符)
- 在C++中将指针数组的所有元素设置为 nullptr
- C++:如何将枚举元素设置为无限?
- 如何在类中初始化数组并为第一个元素设置值
- 如何将Bools中的一个元素设置为true
- 如何将布尔矩阵的每个元素设置为false而不循环
- 将数组中的元素设置为 0 或 NULL
- 使用 while / do-while 循环进行数组元素设置
- C++:数组元素设置为0
- 将元素设置在两个尺寸 std::vector
- 为什么将地图的元素设置为其大小会在分配之前增加大小*
- 如何简洁地将cv::Mat中的每个元素设置为一些标量,如cvSet
- c++默认初始化是否将数组元素设置为默认值?
- 如何将数组中的每个元素设置为0
- 将结构体元素设置为定义中的值
- C++ DirectX11 将同一矢量中的元素设置为同一更新循环中的不同位置