C++ vector容器遍历并删除元素

本文详细介绍了在C++中使用vector迭代器遍历并删除元素时常见的错误及其后果,强调了在调用erase函数后旧迭代器会失效,应当避免在erase后使用旧迭代器。通过示例代码展示了正确和错误的删除方法,并指出这种错误在map中却是可行的。最后,提醒程序员在处理容器的迭代器时要特别小心。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在使用C++ vector的迭代器遍历并删除元素时,存在一些不注意的误区,这里特此记录。

在使用迭代器遍历vector元素时,错误的删除方法:

  vector<int>::iterator it = vec.begin();
  for (; it != vec.end();) {
    vector<int>::iterator tmpit = it;
    it++;
    vec.erase(tmpit);
  }

正确的删除方法:

  vector<int>::iterator it = vec.begin();
  for (; it != vec.end();) {
    it = vec.erase(it);
  }

一个例子:

  vector<int> vec;
  for (int i = 0; i < 20; ++i) {
    vec.push_back(i + 1);
  }
  for (int i = 0; i < vec.size(); ++i) {
    cout << vec[i] << " ";
  }
  cout << endl;

  vector<int>::iterator it = vec.begin();
  for (; it != vec.end();) {
    cout << (*it) << endl;
    if ((*it) % 2 == 1) {
      vector<int>::iterator tmp = it;
      it = vec.erase(tmp);
    } else {
      it++;
    }
  }

  for (int i = 0; i < vec.size(); ++i) {
    cout << vec[i] << " ";
  }
  cout << endl;

 输出结果为:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
1 3 5 7 9 11 13 15 17 19

符合预期!

当使用以上错误的删除方式时,

  vector<int> vec;
  for (int i = 0; i < 20; ++i) {
    vec.push_back(i + 1);
  }
  for (int i = 0; i < vec.size(); ++i) {
    cout << vec[i] << " ";
  }
  cout << endl;

  vector<int>::iterator it = vec.begin();
  for (; it != vec.end();) {
    cout << (*it) << endl;
    if ((*it) % 2 == 0) {
      vector<int>::iterator tmp = it;
      it++;
      vec.erase(tmp);
    } else {
      it++;
    }
  }

  for (int i = 0; i < vec.size(); ++i) {
    cout << vec[i] << " ";
  }
  cout << endl;

输出结果为:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 
1
2
4
6
8
10
12
14
16
18
20
20
Segmentation fault

可以看出,迭代器it的访问已经错乱了。

需要说明的是,vector错误的遍历删除方式,在map中是正确的写法!

补充:

C++11后,可以使用上述的方法删除map元素。

C++用迭代器正确删除map元素_c++ map迭代器删除-优快云博客

重要:vector的erase函数会使迭代器失效,因此,在遍历时使用erase函数后,旧的迭代器就不能再使用了!

看下面一个例子:

  vector<int> vec;

  vec.push_back(1);
  vec.push_back(2);

  vector<int>::iterator it = vec.begin();
  for (; it != vec.end();) {
    cout << (*it) << endl;
    if ((*it) % 2 == 1) {
      vector<int>::iterator tmp = it;

      cout << "before erase:" << (*tmp) << endl;

      it = vec.erase(tmp);

      cout << "after erase:" << (*tmp) << endl;

    } else {
      it++;
    }
  }

输出结果为:

1
before erase:1
after erase:2
2

可以看到,erase前的tmp跟it一样,erase之后,tmp并不是旧的it值。

所以万不可在erase之后去访问旧的迭代器!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值