Ore*_*lom 7 c++ erase stdset c++17
我已经读过这篇SO帖子了,这个也是关于std::set迭代过程中元素的擦除.但是,似乎C++ 17中存在一个更简单的解决方案:
#include <set>
#include <iostream>
int main(int argc,char **argv)
{
std::set<int> s;
s.insert(4);
s.insert(300);
s.insert(25);
s.insert(-8);
for (auto it:s)
{
if (it == -8)
{
s.erase(it);
}
}
std::cout << "s = {";
for (auto it:s)
{
std::cout << it << " ";
}
std::cout << "}\n";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当我编译并运行它时,一切都很完美:
$ g++ -o main main.cpp
$ ./main
s = {4 25 300 }
Run Code Online (Sandbox Code Playgroud)
擦除这样的元素有什么警告吗?谢谢.
Aco*_*gua 12
根据C++ 17标准:
9.5.4基于范围的语句[stmt.ranged]
1基于范围的声明
Run Code Online (Sandbox Code Playgroud)for ( for-range-declaration : for-range-initializer ) statement相当于
Run Code Online (Sandbox Code Playgroud){ auto &&__range = for-range-initializer ; auto __begin = begin-expr ; auto __end = end-expr ; for ( ; __begin != __end; ++__begin ) { for-range-declaration = *__begin; statement } }
所以没有,你的代码是无效的,因为你抹去迭代器当前指向的元素(std::set只能有一个相同的密钥值!),从而得到迭代器失效和递增之后,这是不确定的行为.
要知道,你可以删除另一个从集合元素,如std::set(以及在std::map或std::list)删除只迭代器失效,而所有其他仍然有效.
如果您打算删除容器的当前元素(包括std::vector,erase返回一个新的,有效的迭代器),您需要回退到经典循环,如引用问题的答案所示; 我个人喜欢一个单行的变体:
iter = /*some condition*/ ? container.erase(iter) : std::next(iter);
Run Code Online (Sandbox Code Playgroud)