当一个容器变化时,指向该容器中元素的迭代器可能失效。这使得在迭代器变化期间改变容器容易出现问题。在这方面,不同的容器提供不同的保障:
vectors: 引起内存重新分配的插入运算使所有迭代器失效,插入也使得插入位置及其后位置的迭代器失效,删除运算使得删除位置及其后位置的迭代器失效.
vector的push_back操作可能没事,但是一旦引发内存重分配,所有迭代器都会失效;
vector的insert操作插入点之后的所有迭代器失效;但一旦引发内存重分配,所有迭代器都会失效;
vector的erase操作插入点之后的所有迭代器失效;
vector的reserve操作所有迭代器失效(因为它导致内存重分配);

list/map: 插入不会使得任何迭代器失效;删除运算使指向删除位置的迭代器失效,但是不会失效其他迭代器.
deque的insert操作所有迭代器失效;
deque的erase操作所有迭代器失效;

1. 对于关联容器(如map, set, multimap,multiset),删除当前的iterator,仅仅会使当前的iterator失效,只要在erase时,递增当前iterator即可。这是因为map之类的容器,使用了红黑树来实现,插入、删除一个结点不会对其他结点造成影响。erase迭代器只是被删元素的迭代器失效,但是返回值为void,所以要采用erase(iter++)的方式删除迭代器。
for (iter = cont.begin(); it != cont.end();)
{
   (*iter)->doSomething();
   if (shouldDelete(*iter))
      cont.erase(iter++);
   else
      ++iter;
}

2. 对于序列式容器(如vector,deque),删除当前的iterator会使后面所有元素的iterator都失效。这是因为vetor,deque使用了连续分配的内存,删除一个元素导致后面所有的元素会向前移动一个位置。所以不能使用erase(iter++)的方式,还好erase方法可以返回下一个有效的iterator。
for (iter = cont.begin(); iter != cont.end();)
{
   (*it)->doSomething();
   if (shouldDelete(*iter))
      iter = cont.erase(iter); 
   else
      ++iter;
}
3. 对于list来说,它使用了不连续分配的内存,并且它的erase方法也会返回下一个有效的iterator,因此上面两种方法都可以使用。

删除数组中某个元素后连续重复的元素,例如 1,1,2,3,3,1,1,1,4,0 ---> 1, 2,3,1,4,0。给出问题的一个正确的实现:

  1. #include <iostream>
  2. #include <vector>
  3. using namespace std;
  4. int main(int argc, char* argv[])
  5. {
  6. int a[] = {1, 1, 3, 3, 3, 2, 4, 1, 1, 1, 0};
  7. int size = sizeof(a)/sizeof(a[0]);
  8. vector<int> vec(a, a+size);
  9. vector<int>::iterator iter = vec.begin();
  10. int previous = *iter;
  11. ++iter;
  12. for (; iter != vec.end();)
  13. {
  14. if(*iter == previous)
  15. {
  16. iter = vec.erase(iter);
  17. }
  18. else
  19. {
  20. previous = *iter;
  21. ++iter;
  22. }
  23. }
  24. for(iter = vec.begin(); iter != vec.end(); ++iter)
  25. {
  26. cout << *iter << endl;
  27. }
  28. return 0;
  29. }

PS. 不过实际上这个问题,用vector来实现不是很适合,因为每次删除一个元素,都会引起vector的一个resize操作。resize的时间复杂度是O(n),整个的resize操作要花费O(n^2)。最好是选择list最为容器,list最适合那些需要在容器中间做插入、删除的例子。

【转】失效迭代器(Invalidating Iterators)的更多相关文章

  1. C++ 标准模板库(STL)——迭代器(iterators)的用法及理解

    C++ STL中迭代器(iterators)用于遍历对象集合的元素.由于容器大小随着插入删除等操作动态改变,无法像静态数组那样获取数组长度然后遍历容器里的所有元素:这时就需要迭代器,每次从容器内第一个 ...

  2. C++ STL中迭代器失效的问题

    my_container.erase(iter); 其中my_container是STL的某种容器,iter是指向这个容器中某个元素的迭代器.如果不是在for,while循环中,这种方式删除元素没有问 ...

  3. C++中迭代器原理、失效和简单实现

    目录 迭代器的使用 迭代器的种类 迭代器的失效 迭代器的实现 1.迭代器的使用 为了提高C++编程的效率,STL中提供了许多容器,包括vector.list.map.set等.有些容器例如vector ...

  4. 模拟实现简化版List迭代器&嵌入List

    1.迭代器(iterators)概念(1)迭代器是一种抽象的设计概念,其定义为:提供一种方法,使他能够按顺序遍历某个聚合体(容器)所包含的所有元素,但又不需要暴露该容器的内部表现方式. (2)迭代器是 ...

  5. 【OpenMesh】使用迭代器和循环机

    原文出处: http://openmesh.org/Documentation/OpenMesh-Doc-Latest/tutorial.html 这个例子展现: 如何使用迭代器 如何使用循环机 这个 ...

  6. python的迭代器、生成器、装饰器

    迭代器.生成器.装饰器 在这个实验里我们学习迭代器.生成器.装饰器有关知识. 知识点 迭代器 生成器 生成器表达式 闭包 装饰器 实验步骤 1. 迭代器 Python 迭代器(Iterators)对象 ...

  7. STL迭代器------Traits编程技法详细理解(一)

    最近在看STL源码解析的迭代器(iterators)一章,涉及到c++ Traits的编程技法,刚开始看时一头雾水,反复看了好几遍之后才理解这个东西,因此来写写在这方面的理解,如有错误,希望读者指正. ...

  8. 容器vector 迭代器iterator 应用

    #include <iostream> #include <vector> using namespace std; int main() { vector<int> ...

  9. Qt容器类之二:迭代器

    一.介绍 遍历一个容器可以使用迭代器(iterators)来完成,迭代器提供了一个统一的方法来访问容器中的项目.Qt的容器类提供了两种类型的迭代器:Java风格迭代器和STL风格迭代器.如果只是想按顺 ...

随机推荐

  1. YFCMF 问题

    1.菜单不见了,yf.php  (main 改为0 ) function tagMenu $parseStr .='echo get_menu("main","'.$to ...

  2. UNIX环境编程学习笔记(23)——信号处理初步学习

    lienhua342014-10-29 1 信号的概念 维基百科中关于信号的描述是这样的: 在计算机科学中,信号(英语:Signals)是 Unix.类 Unix 以及其他 POSIX 兼容的操作系统 ...

  3. pytest集成Allure Report

    https://blog.csdn.net/liuchunming033/article/details/79624474#commentBox https://blog.csdn.net/lihua ...

  4. Android 布局学习之——Layout(布局)详解一

    layout(布局)定义了用户界面的可视化结构(visual structure),如Activity的UI,应用窗口的UI. 有两种方式声明layout: 1.在xml文件中声明UI组件. 2.在运 ...

  5. 如何更改webstrom的默认端口63342

  6. 解决sourcesafe admin用户自动登录并且不用密码的问题

    用管理员(admin)登录Microsoft   Visual   SourceSafe   Administration tools-> "SourceSafe   Options界 ...

  7. 基于jQuery的tooltips插件--poshytip

    摘要: 分享一款在项目中使用的tooltips插件--poshytip,这是一款基于jQuery的插件,其特点是简单易用,支持浏览器:IE6+, FF 2+, Opera 9+, Safari 3+, ...

  8. nginx反向代理配置(nginx.conf+proxy_set_header)

    转载:https://blog.csdn.net/bjsunwei/article/details/62231209 location / { proxy_pass http://test; prox ...

  9. [Algorithm] Beating the Binary Search algorithm – Interpolation Search, Galloping Search

    From: http://blog.jobbole.com/73517/ 二分检索是查找有序数组最简单然而最有效的算法之一.现在的问题是,更复杂的算法能不能做的更好?我们先看一下其他方法. 有些情况下 ...

  10. layui文件上传进度条(模拟)

    1.修改上传组件js(没测) https://blog.csdn.net/weixin_42457316/article/details/81017471 https://www.cnblogs.co ...