10

我是 C++ 新手。我想知道有经验的编码员是如何做到这一点的。

我有的:

set<int> s;
s.insert(1);
s.insert(2);
s.insert(3);
s.insert(4);
s.insert(5);

for(set<int>::iterator itr = s.begin(); itr != s.end(); ++itr){
if (!(*itr % 2))
    s.erase(itr);
}

当然,它不起作用。因为它在擦除后递增。这是否意味着每次我从集合中删除元素后,Itr 都必须指向集合的开头?

4

4 回答 4

16
 for(set<int>::iterator itr = s.begin(); itr != s.end(); ){
  if (!(*itr % 2))
      s.erase(itr++);

  else ++itr;
 }

Scott Myers 的有效 STL

于 2010-01-18T19:09:15.677 回答
11

从 std::set 中删除一个元素只会使指向该元素的迭代器无效。

在擦除目标元素之前获取下一个元素的迭代器。

于 2010-01-18T19:05:29.370 回答
8

你不需要回到起点。set::erase仅使引用被擦除项目的迭代器无效,因此您只需要在擦除之前复制迭代器并递增:

for(set<int>::iterator itr = s.begin(); itr != s.end();)
{
    set<int>::iterator here = itr++;
    if (!(*here % 2))
        s.erase(here);
}
于 2010-01-18T19:08:51.620 回答
-1

最好的方法是使用 remove_if 和 erase 的组合

s.erase(remove_if(s.begin(), s.end(), evenOddFunctor), s.end())

这将很有帮助 http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Erase-Remove

另请参阅 scott meyers 的有效 STL

Edit: 虽然我的解决方案是错误的,但我不会删除它。对于像我这样不了解可变/不可变迭代器的人来说,这可能是一个很好的学习

于 2010-01-19T04:20:01.043 回答