在C ++ 17中迭代时从std :: set中移除元素

时间:2018-08-08 10:15:42

标签: c++ c++17 erase stdset

我已经读过this SO postthis 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 }

在擦除类似元素方面是否有警告?谢谢。

2 个答案:

答案 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::setstd::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";
}