如何删除std::vector内的element?(使用for loop) (中级)
初学者若想要删除std::vector内的element,第一个想到的就是用for loop,若该iterator的值是我要删的,就erase
以上的程序,compile可过,但run-time无法执行,为什么呢?若用debug的watch观察,发现iter被erase后,该iter会指向一个不可预期的地址,导致++iter错误,若要用for loop,必须改成以下写法
1
// Compile OK, but run-time error!!
2
for(std::vector<int>::iterator iter = ivec.begin(); iter != ivec.end(); ++iter) {
3
if (*iter == 8) {
4
ivec.erase(iter);
5
}
6
}

2

3

4

5

6

以上的程序,compile可过,但run-time无法执行,为什么呢?若用debug的watch观察,发现iter被erase后,该iter会指向一个不可预期的地址,导致++iter错误,若要用for loop,必须改成以下写法
1
/*
2
(C) OOMusou 2006 http://oomusou.cnblogs.com
3
4
Filename : VectorFindAndEraseByForLoop.cpp
5
Compiler : Visual C++ 8.0
6
Description : Demo how to erase iterator by For Loop.
7
Release : 11/14/2006
8
*/
9
#include <iostream>
10
#include <vector>
11
12
int main() {
13
const int iaSize = 11;
14
int ia[] = {0, 1, 1, 2, 3, 5, 8, 13, 21, 55, 89};
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
}

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

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
4
Filename : ListFindAndEraseByForLoop.cpp
5
Compiler : Visual C++ 8.0
6
Description : Demo how to erase iterator by For Loop.
7
Release : 11/14/2006
8
*/
9
#include <iostream>
10
#include <list>
11
12
int 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
}

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

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