我已经读过this SO post和this one too关于
在迭代过程中从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;
}
当我编译并运行它时,一切都变得完美了:
$ g++ -o main main.cpp
$ ./main
s = {4 25 300 }
在擦除类似元素方面是否有警告?谢谢。
答案 0 :(得分:11)
根据C ++ 17标准:
9.5.4基于范围的语句[stmt.ranged]
1基于范围的for语句
let request = NSMutableURLRequest(url: NSURL(string: "http://himynameis.com/api/v1/user/getUserProfile/9")! as URL, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0) request.httpMethod = "GET" let session = URLSession.shared let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in if (error != nil) { print(error) } else { let httpResponse = response as? HTTPURLResponse print(httpResponse) } }) dataTask.resume()
等同于
for ( for-range-declaration : for-range-initializer ) statement
因此否,您的代码无效,因为您删除了迭代器当前指向的元素({
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
返回一个新的有效迭代器),则需要回退到经典循环,如answer引用的问题;我个人喜欢:
erase
答案 1 :(得分:0)
如果您的C ++实现支持Library Fundamentals TS(第二版),则可以执行以下操作:
#include <experimental/set>
#include <iostream>
#include <algorithm>
#include <experimental/iterator>
int main()
{
std::set<int> s;
s.insert(4);
s.insert(300);
s.insert(25);
s.insert(-8);
std::experimental::erase_if(s,
[](auto& key){ return key == -8; });
std::cout << "s = {";
std::copy(s.begin(), s.end(),
std::experimental::make_ostream_joiner(std::cout, " "));
std::cout << "}\n";
}