如何删除std::vector内的element?(使用for loop) (中级)

初学者若想要删除std::vector内的element,第一个想到的就是用for loop,若该iterator的值是我要删的,就erase


1// Compile OK, but run-time error!!
2for(std::vector<int>::iterator iter = ivec.begin(); iter != ivec.end(); ++iter) {
3  if (*iter == 8{
4    ivec.erase(iter);
5  }

6}


以上的程序,compile可过,但run-time无法执行,为什么呢?若用debug的watch观察,发现iter被erase后,该iter会指向一个不可预期的地址,导致++iter错误,若要用for loop,必须改成以下写法


 1/* 
 2(C) OOMusou 2006 http://oomusou.cnblogs.com
 3
 4Filename    : VectorFindAndEraseByForLoop.cpp
 5Compiler    : Visual C++ 8.0
 6Description : Demo how to erase iterator by For Loop.
 7Release     : 11/14/2006
 8*/

 9#include <iostream>
10#include <vector>
11
12int main() {
13  const int iaSize = 11;
14  int ia[] = {011235813215589};
15
16  std::vector<int> ivec;
17  ivec.insert(ivec.end(), ia, ia + iaSize);
18
19   // Compile OK, but run-time error!!
20   //for(std::vector<int>::iterator iter = ivec.begin();
21   // iter != ivec.end(); ++iter) {
22   //   if (*iter == 8) {
23   //     ivec.erase(iter);
24   //   }
25   //}
26
27  // Compile OK, run-time OK!!
28  for(std::vector<int>::iterator iter = ivec.begin();
29    iter != ivec.end(); ++iter) {
30      if (*iter == 8{
31        --(iter = ivec.erase(iter));
32      }

33  }
 
34 
35  // cout the result
36  for(std::vector<int>::const_iterator iter = ivec.begin();
37    iter != ivec.end(); ++iter) {
38
39      std::cout << *iter << std::endl;
40  }

41
42  return 0;
43}


vector.erase()删除iterator后,会传回下一个iterator的pointer,若在由for loop的++iter,则会少考虑了被删除后的下一个iterator,故需加上--,将iterator往前移,移到被删除的iterator的前一个iterator,这样for loop的++iterator才会考虑到被删除的下一个iterator。


为了证明这个方法可行,而不是只适用于vector(因为常发现vector可跑的程序,在其它container却不能跑),特别将原程序改成list,证明此法正确。

 1/* 
 2(C) OOMusou 2006 http://oomusou.cnblogs.com
 3
 4Filename    : ListFindAndEraseByForLoop.cpp
 5Compiler    : Visual C++ 8.0
 6Description : Demo how to erase iterator by For Loop.
 7Release     : 11/14/2006
 8*/

 9#include <iostream>
10#include <list>
11
12int main() {
13
14  std::list<int> ilist;
15  for(int i = 0; i != 10++i) {
16    ilist.push_back(i);
17  }

18
19   // Compile OK, but run-time error!!
20   //for(std::list<int>::iterator iter = ilist.begin();
21   // iter != ilist.end(); ++iter) {
22   //   if (*iter == 8) {
23   //     ilist.erase(iter);
24   //   }
25   //}
26
27   for(std::list<int>::iterator iter = ilist.begin();
28    iter != ilist.end(); ++iter) {
29      if (*iter == 8{
30        --(iter = ilist.erase(iter));
31      }

32   }

33 
34  // cout the result
35  for(std::list<int>::const_iterator iter = ilist.begin();
36    iter != ilist.end(); ++iter) {
37
38      std::cout << *iter << std::endl;
39  }

40
41  return 0;
42}

 


其实这并不是建议的方式,只是demo若还是要用for loop写,该怎么改成可以执行的程序,但可以发现程序相当的『丑』,修修补补的痕迹非常明显,正规的作法该用find()这个generic algorithm找到要删除的iterator后,直接删除,请参阅如何删除std::vector内的element?(使用find) (初级)

See Also
如何删除std::vector内的element?(使用find) (初级)

posted on 2006-11-15 14:27  真 OO无双  阅读(10634)  评论(2编辑  收藏  举报

导航