C++ STL 迭代器失效问题

deque 迭代器失效的问题详解 今天在看STL源码的时候,无意写了如下的代码,发现程序崩溃了: deque::iterator iter=d.begin(); d.insert(iter,5); d.insert(iter,6); //崩溃,迭代器失效了 之前一直没有留意这个问题,后来结合源码和查找资料,得到如下的结论: 插入操作: 1、在队前或队后插入元素时(push_back(),pus 阅读详情
之前看《C++ Primier》的时候,也解到在顺序型窗口里insert/erase会涉及到迭代器失效的问题,并没有深究。今天写程序的时候遇到了这个问题。
1 莫名其妙的Erase  

  最初我的程序是酱紫的,别说话,我知道这样是有问题的,可这样是最直观的想法

   int arr[]={0,1,2,3,4,5,6,7,8,9,10}; 
  vector<int> a(arr,arr+sizeof(arr)/sizeof(*arr));for (auto it = a.begin(); it != a.end();++it ){ if ((*it)&1){ a.erase(it); } }

  没错,程序崩溃!删除了迭代器it之后,it迭代器失效了,无法再进行++it操作了。

  可是,当我觉得erase做的只是把it之后的元素向前移动一个位置而已,为什么迭代器失效了呢?我翻开《STL源码剖析》,SGI STL的vector<T,Alloc>::erase的源码是这样的:

iterator vector<T, Alloc>::erase(iterator position)
    {
        if (position + 1 != end())
            copy(position + 1, finish, position);
        --finish;
        destroy(finish);
        return position;
    }

  正如我所想,erase函数并没有对输入的position迭代器进行改写!我打印出调试信息,发现erase之后,迭代器的_Ptr成员,也就是指针的值并没有发生变化,而此指针所指的元素的确是下一个元素。那么为什么失效了呢?

  我又查了《C++ Primier》,发现此书上的标准写法是这样的:

int arr[]={0,1,2,3,4,5,6,7,8,9,10}; 
  vector<int> a(arr,arr+sizeof(arr)/sizeof(*arr));
    for (auto it = a.begin(); it != a.end();){
        if ((*it)&1){
            it=a.erase(it);
        }
        else
            ++it;    
    }  

  运行了一下,这样是没错的。我打印了调试信息,发现与之前一样,erase之后把结果赋给it,it里的成员_Ptr并没有发生变化。唯一的可能就是迭代器里还有别的标志,如果当前元素被删除之后,该迭代器也就“失效”了。《C++ Primier》并未对此作出过多解释,只是说,erase函数返回被删除元素的下一个元素的迭代器。

  结论:在STL里,我们不能以指针来看待迭代器,指针是与内存绑定的,而迭代器是与容器里的元素绑定的,删除了之后,该迭代器就失效了,在对其重新赋值之前,不能再访问此迭代器。

2 更加小心冀冀地Insert

  机智如我,自然会去探索一下insert之后,迭代器会怎样。于是:  

    vector<int> a;
    for (int i = 0; i < 10; ++i)
    {
        a.push_back(i);
    }

    for (auto it = a.begin(); it != a.end(); ++it){
        if (*it == 5){ 
            a.insert(it, 100);
       ++it; } }

  你猜怎么着??

  啥事儿没有!你可能会问,插入之后为什么要++it。插入之前,it指向5,在5之前插入100后,it指向100。这样下一次循环,it依然会指向5。相信我,你的程序会爆炸的!

  我作了个++it之后,it又指向5,下一次循环就直接指向5之后的元素了,顺利完成插入工作。

  世界和平~世界和平~我还真不确定。

  突然想到,当插入元素过多,vector的capacity会增加,这时会不会问题呢?说干就干:  

    vector<int> a;
    for (int i = 0; i < 13; ++i)
    {
        a.push_back(i);
    }

    for (auto it = a.begin(); it != a.end(); ++it){
        if (*it == 5){ 
            a.insert(it, 100);
       ++it;
        }
    }  

  BOOM!果然崩溃了!也就是说插入之后的迭代器失效了。那之前的呢?

  我决定粗暴地测试一下:

    vector<int> a;
    for (int i = 0; i < 13; ++i)
    {
        a.push_back(i);
    }
    auto it1=a.begin();
    for (auto it = it1; it != a.end(); ++it){
        if (*it == 5){ 
            a.insert(it, 100);
        it=it1;
        }
    }  

  我插入之后,直接让it指向begin(),然后单步调试。执行完it=it1还好好的,可再去执行++it还是崩溃了。

  也就是说,capacity变化之后,所有的迭代器都失效了!这是当然了呀!capacity发生变化,容器内部做的不仅仅是增加capacity这么简单,因为容器所在内存后面可能没有足够的内存让我们使用,所以,容器要重新开辟一段足够大的内存来存储容器里的元素,当前内存会被释放。这样一来,迭代器自然失效了。

3 C++ Primier的总结

  关于容器的迭代器失效的问题,C++ Primier用了一小节作了总结,我翻译成中文如下:

  (1)增加元素到容器后

  对于vector和string,如果容器内存被重新分配,iterators,pointers,references失效;如果没有重新分配,那么插入点之前的iterator有效,插入点之后的iterator失效;

  对于deque,如果插入点位于除front和back的其它位置,iterators,pointers,references失效;当我们插入元素到front和back时,deque的迭代器失效,但reference和pointers有效;

  对于list和forward_list,所有的iterator,pointer和refercnce有效。

  (2)从容器中移除元素后

  对于vector和string,插入点之前的iterators,pointers,references有效;off-the-end迭代器总是失效的;

  对于deque,如果插入点位于除front和back的其它位置,iterators,pointers,references失效;当我们插入元素到front和back时,off-the-end失效,其他的iterators,pointers,references有效;

  对于list和forward_list,所有的iterator,pointer和refercnce有效。

  (3)在循环中refresh迭代器

  当处理vector,string,deque时,当在一个循环中可能增加或移除元素时,要考虑到迭代器可能会失效的问题。我们一定要refresh迭代器。

int arr[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    deque<int> v(arr,arr+sizeof(arr)/sizeof(*arr));
    for (auto it = v.begin(); it != v.end(); )
    {
        if ((*it) & 1)
        {
            it = v.insert(it, *it);
            it += 2;
        }
        else
            it = v.erase(it);
    }

  至于it+=2,很容易解释,insert之后,it指向新增加的元素,+2之后,it指向下一个要处理的元素。

  (4)在循环不变式中不要store off-the-end迭代器

  这个很容易理解了,增加或移除元素之后,off-the-end失效了,不store的话,每次从end()函数中取的都是最新的off-the-end,自然不会失效。

  最后:《C++ Primier》是本好书。

  

  

C++中STL中vector和list的迭代器失效问题 C++ 中vector和list是我们常用的容器,在容器配合算法的时候,就用到了迭代器。 这样提高了代码的可读性,也配合了STL中的算法。但是在容器中使用迭代器时候会发生迭代器失效问题,所以我们就得注意。 首先我们看vector的迭代器失效问题 在vector中迭代器失效发生在insert和erase中。 我们先看insert,在vector中插入元素,插入元素后当发现开辟的空间不够了... 阅读详情

相关推荐

FFmpeg魔改指南:让RTMP协议完美兼容H265的三种方法(含SRS适配技巧)

本文详细介绍了三种让RTMP协议兼容H265编码的FFmpeg魔改方案,包括基于官方补丁的标准改造、Intel的SVT-HEVC集成方案以及金山云的自定义扩展方案。文章重点解析了各方案的实现原理与适配技巧,并提供了在SRS 6.0服务器上进行深度配置和性能调优的完整实战指南,帮助开发者解决H265推流至传统RTMP服务器的兼容性问题。

weixin_29290947的博客 195

STL迭代器失效的场景总结

STL迭代器失效的场景总结

qq_43148810的博客 1871

KF-gins输出结果绘图

KF-gins输出结果绘图

m0_51977577的博客 1107

STL(三)删除元素 remove、erase

STL功能很强大,但是说到删除元素,不少人会觉得有些上头,这里,用vector和list两个最常用容器举例。

叶孤城 9802

BUUCTF reverse题解汇总

BUUCTF平台刷题过程中做的一些逆向题解的总结归类

于高山之巅,方见大河奔涌;于群峰之上,更觉长风浩荡。 1万+

微信本地数据解密实战:从AES加密原理到EnMicroMsg.db恢复指南

数据加密是保障信息安全的核心技术,其中对称加密算法AES因其高效可靠,被广泛应用于各类本地数据保护场景。其原理是通过特定密钥对数据进行混淆转换,确保未经授权者无法读取原始内容。在移动应用领域,本地数据库加密对于保护用户隐私、防止数据泄露具有重要价值。微信作为国民级应用,对其本地存储的聊天记录数据库(EnMicroMsg.db)采用了基于设备标识和用户UIN生成的AES-256-CBC加密方案。理解这一机制,不仅有助于在合法合规前提下进行个人数据备份与恢复,也为开发者进行客户端安全分析、兼容工具开发提供了基础

weixin_30764883的博客 570

deque及迭代器失效问题

deque由一段一段的定量连续空间构成,采用一个表(map)来记录每个连续空间的首址,map是一小块连续的空间,目的是便于迭代器的寻址(map+1即可跳转到下一个连续空间的首址)。map中的每一个元素(node)都是指针,指向另一端(较大的)连续线性空间,称为缓冲区,缓冲区才是deque的储存空间主体。具体机制如下所示: 其中,对迭代器it的解引用得到的是cur位置处对应的元素。 de

ww32cc的博客 5180

【华为OD技术面】 - 考到的Lettcode手撕算法代码真题目录

【华为OD技术面 - 考到的Lettcode手撕算法代码真题目录

算法大师! 7812

标准模板库绕不过的坎-迭代器失效,常用的处理方法

1. 对于序列式容器(如vector,deque),序列式容器就是数组式容器,删除当前的iterator会使后面所有元素的iterator都失效。这是因为vetor,deque使用了连续分配的内存,删除一个元素导致后面所有的元素会向前移动一个位置。所以不能使用erase(iter++)的方式,还好erase方法可以返回下一个有效的iterator。 for (iter = cont.begin(); iter != cont.end();) { (*it)->..

肖邦的夜曲的专栏 383

手把手教你学simulink(16.8)--基于Simulink的小波变换滤波器(Wavelet Transform Filter)项目

基于Simulink的小波变换滤波器(Wavelet Transform Filter)项目的详细实例介绍。这个项目将重点放在小波变换滤波器的设计、实现和仿真上,帮助你理解和应用小波变换滤波器在信号处理中的作用。

MHD0815的博客 534

微信小程序|基于小程序实现定位打卡功能

此文主要在小程序内实现打卡功能,可根据用户位置与公司设定的打卡范围实时判断打卡是否合法,并在后台对打卡记录进行管理。

商务合作 / 项目定制 / 学习交流。个人vx:lovely_wml 1万+

【C++】STL容器中的迭代器失效问题

什么是迭代器失效?在 C++ 中,。但在对容器执行某些操作(如插入、删除、扩容等)后,,也就是说,它指向的内容不再可靠,继续使用会导致程序崩溃或产生未定义行为,这种现象被称为。为什么会失效?对于像vector这类连续存储容器,一旦发生扩容,其内部元素的位置就会整体迁移,原先的迭代器(指针)指向的是旧地址,自然就失效了。删除元素后,容器可能会移动其他元素填补空位,导致原迭代器指向的元素不存在或顺序变化。插入元素也可能使部分迭代器变得不可靠,尤其是插入点之后的迭代器。

qq_48178317的博客 848

【大数据技术干货】(还不懂数仓,数据中心?看这一篇就够了!)在实际的开发生产中,让你了解企业级数据中心整体架构(DB+ETL+ODS+DW+DM)的各个层次的过程详解,数据联系及功能区分

一 企业级数据中心架构 数据仓库的整体架构,各个系统的元数据通过ETL同步到操作性数据仓库ODS中,对ODS数据进行面向主题域建模形成DW(数据仓库),DM是针对某一个业务领域建立模型,具体用户(决策层)查看DM生成的报表。 二 DB 三 ETL(Extract-Transform-Load) ETL是将业务系统的数据经过抽取、清洗转换之后加载到数据仓库的过程,目的是将企业中的分散、零乱、标准不统一的数据整合到一起,为企业的决策提供分析依据。 ETL是BI项目重要的一个环节。 通常情况下,在BI项目中ET

liuchunhang的博客 1289

【C++进阶】深入STL之vector:深入研究迭代器失效及拷贝问题

在C++的STL(Standard Template Library)库中,vector容器无疑是最常用且功能强大的数据结构之一。它提供了动态数组的功能,允许我们在运行时动态地增加或减少元素。然而,随着我们对vector的深入使用,一些潜在的问题也逐渐浮现,其中最为常见和棘手的就是迭代器失效以及拷贝问题

EterNity_TiMe_的计算机学习之路 2381

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

【C++】STL--Vector迭代器失效问题

本文深入探讨了C++ vector中迭代器失效问题。主要包括:1)空间改变操作(如扩容)会导致迭代器指向旧空间而失效;2)元素删除操作可能导致迭代器失效,特别是尾删时;3)对比VS和g++编译器对失效迭代器的处理差异,VS更严格而g++可能有隐患。文章通过代码示例说明失效场景,并强调无论何种编译器都应重新赋值失效迭代器以确保程序正确性。

小陈为梦想而生 897

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

C++——STL的迭代器失效问题

本文转载自:https://blog.youkuaiyun.com/coderCong/article/details/52065130 之前看《C++ Primier》的时候,也解到在顺序型窗口里insert/erase会涉及到迭代器失效的问题,并没有深究。今天写程序的时候遇到了这个问题。 1 莫名其妙的Erase     最初我的程序是酱紫的,别说话,我知道这样是有问题的,可这样是最直观的想法 ...

Lycorisradiata__的博客 339

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

C++初阶学习第十弹——探索STL奥秘(五)——深入讲解vector的迭代器失效问题

探索STL奥秘(五)之——vector的迭代器失效问题(新手极容易出错,一定要好好看看!!!)

2301_80220607的博客 3445

C++ stl中的vector的相关用法 迭代器失效问题

1、vector是用于表示可变大小数组的序列容器。2、vector就像数组一样,采用的是连续的空间来存储元素,也意味着可以通过下标对vector的元素进行访问和修改。3、普通数组的大小不可以动态改变,vector的大小可以动态改变。4、当vector需要重新分配大小时,其做法是,分配一个新的数组,然后将全部元素移到这个数组当中,并释放原来的数组空间。5、vector分配空间策略:vector会分配一些额外的空间以适应可能的增长,因此存储空间比实际需要的存储空间一般更大。

fallzzzzz的博客 832

【C++STL】迭代器分类 失效问题

正向迭代器iterator容器.begin()容器.end()正向遍历容器内元素常正向迭代器容器.cbegin()容器.cend()正向遍历容器内的常量元素反向迭代器容器.rbegin()容器.rend()反向遍历容器内元素常反向迭代器容器.crbegin()容器.crend()反向遍历容器内的常量元素int main()//正向迭代器while (it!it++;//常正向迭代器while (cit!cit++;//反向迭代器。

努力让自己的能力配得上梦想. 830

c++STL容器中vector的使用,模拟实现及迭代器使用注意事项和迭代器失效问题

在前面的章节我们已经接触过了关于STL的知识,也就是string类,我们详细介绍了string类的特性及使用,而严格来说string类并没有被归为STL中,因为string类的出现早于STL,string类的接口也比STL中的单个类多,使得string类较其他类显得冗余,这一期我们就要开始讲STL中的内容。1. vector是表示可变大小数组的序列容器。2. 就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问,和数组一样高效。

qq_58761784的博客 2073

【C++】STL的迭代器失效问题

迭代器失效

xiaomage1213888的博客 1755

C++ stl迭代器 (迭代器失效问题)

C++剖析stl 迭代器是什么?:迭代器 和 指针;迭代器失效;详解`vector`迭代器失效

知识分享与学习笔记总结,欢迎指点 4667

[C++] STL_vector 迭代器失效问题

STL_vector迭代器失效问题分析+解决方案

Ljy_cx_21_4_3的博客 3104

C++ stl迭代器 (迭代器失效问题)_c++ 迭代器失效

🥦 迭代器是指向元素范围(如数组或容器)中的某个元素的任何对象,它能够使用一组运算符(至少具有自增(++) 和解引用 (*) 运算符)循环访问该范围的元素。🍊 迭代器最明显的形式是指针:指针可以指向数组中的元素,并且可以使用增量运算符 (++) 循环访问这些元素。但其他类型的迭代器也是可能的。例如,每个容器类型(如list )都有一个特定的迭代器类型,旨在循环访问其元素。

2401_87255253的博客 1338

C++ STL中迭代器失效问题

C++ STL中迭代器失效问题其实,在我们学习过程中,C++ STL使我们必须要用的一个库,里面集成了很多的数据结构和算法,这些在我们写程序的时候,用的特别多。但是,使用这些,我们经常会出现一些问题,毕竟C++中内存的申请和释放都是程序员亲自去做的,所以说,在使用STL的时候,我们也会遇到很多问题,其中一个就是我们所谓的迭代器。迭代器,其实我们用通俗的理解就是类似于我们使用指针去遍历数组,然后访问元

Travelerwz的博客 782

C++ STL 容器迭代器失效问题

C++ STL 容器迭代器失效问题

huakeh_420的博客 208
上一篇: 面向对象编程要点
下一篇: new与malloc的区别
coderCong
博客等级 码龄12年 12粉丝 31原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值