2010-06-16 183 views
7

以下代码无法正常工作。它应该如何正确地完成?如何遍历STL集合并选择性地删除元素?

for (std::set<Color>::iterator i = myColorContainer.begin(); 
      i!=myColorContainer.end(); 
      ++i) 
{ 
    if (*i == Yellow) 
    { 
     DoSomeProccessing(*i); 
     myColorContainer.erase(i); 
    } 
} 

回答

6

你并不需要一个循环为您选择处理一组。

std::set<Color>::iterator it = myColorContainer.find(Yellow); 
if (it != it.myColorContainer.end()){ 
    DoSomeProcessing(*it); 
    myColorContainer.erase(it); 
} 
+1

代码符合标准。我同意@Viktor Sehr这将是从集合中删除元素的首选方法。但是,该问题询问如何让代码段工作。 – 2010-06-17 09:21:57

+0

@daramarak:我认为你在编辑代码的时候回答了(认为它是我第一篇文章中的std :: vector) – 2010-06-17 09:41:30

7

尝试:

for(std::set<Color>::iterator it = myColorContainer.begin(); 
    it != myColorContainer.end();) { // note missing it++ 
    if((*it) == Yellow) { 
     DoSomeProcessing(*it); 
     myColorContainer.erase(it++); // post increment (original sent to erase) 
    } 
    else { 
     ++it; // more efficient than it++; 
    } 
} 
+0

这也行不通。您应该再次将擦除的返回值分配给它。 – Patrick 2010-06-16 10:46:14

+0

返回的迭代器是打破标准的微软特定实现:http://msdn.microsoft.com/en-us/library/8h4a3515%28VS.80%29.aspx。果然,你需要在擦除之后递增迭代器。 – 2010-06-16 10:53:27

+1

如果您不能使用m $特定的实现并需要使用循环,则此溶剂是完美的。如果你不需要使用循环,Viktor的选择甚至更好。谢谢你的回答。你一直在帮助很大。 – scippie 2012-03-18 22:54:04

2
for (std::set<Color>::iterator i = myColorContainer.begin(); 
      i!=myColorContainer.end(); /* No i++ */) 
{ 
    if (*i == Yellow) 
    { 
     DoSomeProccessing(*i); 
     std::set<Color>::iterator tmp = i; 
     ++i; 
     myColorContainer.erase(tmp); 
    } 
    else { 
     ++i; 
    } 
} 

一旦你进入下一消息++i可以保证它是有效的 - 这对插入的元素的迭代器,除非该元素 被删除永远不会失效的std::set财产。

因此,现在您可以安全地删除以前的条目。