没有躲过的坑--vector使用erase后迭代器变成野指针

没有躲过的坑--vector使用erase后迭代器变成野指针以及remove和erase的区别

      本博客转载自:http://blog.youkuaiyun.com/wangshubo1989/article/details/50121059http://blog.youkuaiyun.com/vbanglev/article/details/1512521并做了适当修改。

      vector上镜率非常高,但是最近又被他fuck了一下。使用的就是vector的erase方法。

      erase–return value
      首先需要明确一下vector的两种erase:
      C++98中是这样的:

iterator erase (iterator position);
iterator erase (iterator first, iterator last)
      C++11中是这样的:

iterator erase (const_iterator position);
iterator erase (const_iterator first, const_iterator last);
      我们使用下面的代码进行erase:
#include <iostream>
#include <vector>

int main ()
{
  std::vector<int> myvector;

  // set some values (from 1 to 10)
  for (int i=1; i<=10; i++) myvector.push_back(i);

  // erase the 6th element
  myvector.erase (myvector.begin()+5);

  // erase the first 3 elements:
  myvector.erase (myvector.begin(),myvector.begin()+3);

  std::cout << "myvector contains:";
  for (unsigned i=0; i<myvector.size(); ++i)
    std::cout << ' ' << myvector[i];
  std::cout << '\n';

  return 0;
}
/*--------------------------------------
Output:
myvector contains: 4 5 7 8 9 10
---------------------------------------*/
      上面的代码非常的完美,但是当把ease用于for循环的时候,就完蛋了:
for(vector<int>::iterator iter=vector_database.begin(); vector_database!=veci.end(); iter++)
{
      if( *iter == 10)
      {
          vector_database.erase(iter);
      }
}
      当执行veci.erase(iter)后,迭代器iter指向了哪里?

      也就是说veci.erase(iter)后,iter的状态是不确定的,成为了野指针!!!再进行++,岂有不崩溃的道理!!
      解决方法是利用erase()函数的返回值对iter重新赋值就好了。
      remove or erase? (这里简单说一下。。)
      很多人还用到过remove,但是对于很多人不能分清楚remove和erase的区别?
      STL中remove()只是将待删除元素之后的元素移动到vector的前端,而不是删除。若要真正移除,需要搭配使用erase()。
      vector中的remove的作用是将等于value的元素放到vector的尾部,但并不减少vector的size
      vector中erase的作用是删除掉某个位置position或一段区域(begin, end)中的元素,减少其size

      非常简要地说一下,remove移动指定区间中的元素直到所有“不删除的”元素在区间的开头(相对位置和原来它们的一样)。它返回一个指向最后一个的下一个“不删除的”元素的迭代器。返回值是区间的“新逻辑终点”。

使用 `vector` 的迭代器时,如果对 `vector` 进行了修改操作(如插入、删除、扩容等),可能会导致原有迭代器失效。这是由于 `vector` 在扩容时会重新分配内存空间,并将原有数据复制到新空间中,原有迭代器仍然指向旧的内存地址,从而成为“指针”。为了避免这一问题,需要及时更新迭代器。 以下是几种常见的 `vector` 迭代器更新方法: ### 插入元素后的迭代器更新 当使用 `insert()` 方法向 `vector` 中插入元素时,插入位置之后的所有迭代器都会失效。这是因为插入可能导致 `vector` 扩容或元素移动[^2]。因此,在插入操作后应重新获取迭代器。 ```cpp std::vector<int> vec = {1, 2, 4, 5}; auto it = vec.begin() + 2; // 指向值为4的元素 it = vec.insert(it, 3); // 插入3,返回指向新插入元素的迭代器[^3] ``` ### 删除元素后的迭代器更新 使用 `erase()` 删除元素时,被删除元素及其之后的迭代器都会失效。因此,在删除操作后应使用 `erase()` 返回的新迭代器继续遍历。 ```cpp std::vector<int> vec = {1, 2, 3, 4, 5}; auto it = vec.begin() + 2; // 指向值为3的元素 it = vec.erase(it); // 删除3,返回指向下一个有效元素的迭代器[^2] ``` ### 扩容或修改容量后的迭代器更新 当 `vector` 发生扩容(如调用 `push_back()`、`resize()`、`reserve()` 等操作)时,原有的迭代器可能失效。此时应重新获取迭代器。 ```cpp std::vector<int> vec = {1, 2, 3}; vec.reserve(10); // 扩容,原迭代器失效 auto it = vec.begin(); // 重新获取迭代器[^3] ``` ### 使用范围 for 循环避免手动管理迭代器 如果不需要对 `vector` 进行复杂的插入或删除操作,可以使用范围 `for` 循环来简化遍历过程,避免手动管理迭代器的复杂性。 ```cpp std::vector<int> vec = {1, 2, 3, 4, 5}; for (const auto& val : vec) { std::cout << val << " "; } ``` ### 总结 - 插入或删除操作后,必须使用 `insert()` 或 `erase()` 返回的新迭代器- 扩容操作后,应重新获取迭代器- 若无需复杂操作,建议使用范围 `for` 循环代替传统迭代器遍历方式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值