迭代器C11
创始人
2024-02-01 20:57:12

迭代器

迭代器失效

容器使用迭代器时,不要改变容器的大小

/在操作迭代器的过程中(使用了迭代器这种循环体),千万不要改变vectori容器的容量,也就是不要增加或者删除vectori容器中的元素
/往容器中增加或者从容器中删除元素,这些操作可能会使指向容器元素的指针、引用、迭代器失效。
失效就表示不能再代表任何容器中的元素。一旦使用失效的东西,就等于犯了严重的程序错误,很多情况下,程序会直接崩溃。

原迭代器指的是进行操作之前保存的迭代器,包括begin()、end()以及其他位置的迭代器。

vector:

成员函数push_back():会在容器末尾添加一个元素。如果容器有剩余空间(capacity() > size()),则直接添加新元素到容器尾部。此时,原迭代器中end()会失效,其他的都不会失效。否则,会导致容器重新分配内存,然后将数据从原内存复制到新内存,再在尾部添加新元素。此时,由于内存重新分配,原迭代器(所有)都失效。

成员函数pop_back():直接将容器中的最后一个元素删除,原迭代器中end()会失效,其余的都不会失效。

成员函数insert(iterator, n):如果容器有剩余空间,先在容器尾部插入一个元素,然后将插入点及之后的元素都向后移动一位,然后在插入点创建新元素。否则,会导致容器重新分配内存,接着将插入点之前的元素复制过去,在插入点创建新元素,再将插入点之后的元素复制过去。因此,如果没有内存的重新分配,原迭代器中插入点及插入点之后的迭代器(包括end())都失效。如果有内存的重新分配,原迭代器(所有)都失效。

成员函数erase(iterator):将删除点及之后的元素都向前移动一位,然后删除最后一个元素。因此,原迭代器中删除点之前的迭代器都有效,插入点及插入点之后的迭代器都失效。

deque:

成员函数push_back():会直接在容器末尾添加一个元素。原迭代器中end()会失效,其他的都不会失效。

成员函数push_front():会直接在容器头部添加一个元素。原迭代器中begin()会失效,其他的都不会失效。

成员函数pop_back():会直接删除最后一个元素。原迭代器中end()会失效,其他的都不会失效

成员函数pop_front():会直接在容器头部删除一个元素。原迭代器中begin()会失效,其他的都不会失效。

成员函数insert(iterator, n):如果插入点之前的元素较少,会在容器头部插入一个元素,然后将插入点及其之前的所有元素向前移动一位,再在插入点创建新元素。否则,将插入点及其之后的元素向后移动一位,再在插入点创建新元素。因此,向前移动则导致原迭代器中插入点及插入点之前的迭代器都失效;向后移动则导致迭代器中插入点及插入点之后的迭代器都失效。

成员函数erase(iterator):如果删除点之前的元素较少,将删除点之前的所有元素向后移动一位,再删除第一个元素。否则,将删除点之后的所有元素向前移动一位,再删除最后一个元素。因此,向前移动将导致原迭代器中删除点及删除点之后的迭代器失效;向后移动将导致原迭代器中删除点及删除点之前的迭代器都失效。

list:

因为list的底层结构是双向链表,所有操作都只是针对节点移动指针,不会涉及到位置变化,操作影响的范围很小。

成员函数push_back():原迭代器中end()会失效,其他的都不会失效。

成员函数push_front():原迭代器中begin()会失效,其他的都不会失效。

成员函数pop_back():原迭代器中end()会失效,其他的都不会失效

成员函数pop_front():原迭代器中begin()会失效,其他的都不会失效。

成员函数insert(iterator, n):原迭代器中插入点会失效,其他的都不会失效。

成员函数erase(iterator):原迭代器中删除点会失效,其他的都不会失效。

set、multiset、map、multimap

关联容器的底层结构为红黑树,所有操作同list一样,都只是移动指针,各成员函数导致的迭代器失效问题同list。

防止迭代器失效

  vector v1;v1.push_back(1);v1.push_back(2);v1.push_back(3);v1.push_back(4);v1.push_back(5);vector::iterator it = find(v1.begin(), v1.end(), 2);if (it != v1.end()){it=v1.insert(it, 20);//及时更新了it指向的位置}

序列性容器::(vector和list和deque)
erase迭代器不仅使所指向被删元素的迭代器失效,而且使被删元素之后的所有迭代器失效,所以不能使用erase(iter++)的方式,但是erase的返回值为下一个有效的迭代器。

    所以正确方法为::for( iter = c.begin(); iter != c.end(); )iter = c.erase(iter);

关联性容器::(map和set比较常用)
erase迭代器只是被删元素的迭代器失效,但是返回值为void,所以要采用erase(iter++)的方式删除迭代器,
所以正确方法为::

for( iter = c.begin(); iter != c.end(); )
c.erase(iter++);

Tips:
其实对于list两种方式都可以正常工作

vector容器释放堆内存

如果要在Vector容器中存放结构体类型的变量,经常见到两种存放方式.

方式一:放入这个结构体类型变量的副本。

方式二:放入指向这个结构体类型变量的指针。

假设结构体类型变量是这样的,

typedef struct student{char school_name[100];char gender;int age;bool is_absent;
} StudentInfo;

那么,方式一和方式二的实现分别如下所示:

/*[方式一] 结构体放栈中,vector中放副本---------------------*/
#include 
#include 
#include 
typedef struct student{char school_name[100];char gender;int age;bool is_absent;
} StudentInfo;typedefstd::vector StudentInfoVec;void print(StudentInfoVec* stduentinfovec){for (int j=0;j<(*stduentinfovec).size();j++){std::cout<<(*stduentinfovec)[j].school_name<<"\t"<<(*stduentinfovec)[j].gender<<"\t"<<(*stduentinfovec)[j].age<<"\t"<<(*stduentinfovec)[j].is_absent<<"\t"<StudentInfo micheal={"Micheal",'m',18,false};StudentInfo cherry={"Cherry",'f',16,true};StudentInfoVec studentinfovec;studentinfovec.push_back(micheal);studentinfovec.push_back(cherry);print(&studentinfovec);return 0;
}

image-20221117232051188

/*[方式二]  结构体放入堆中,vector中放指针---------------------*/
typedef struct student{char* school_name;char gender;int age;bool is_absent;
} StudentInfo;typedefstd::vector StudentInfoPtrVec;void print(StudentInfoPtrVec*stduentinfoptrvec){for (int j=0;j<(*stduentinfoptrvec).size();j++){std::cout<<(*stduentinfoptrvec)[j]->school_name<<"\t"<<(*stduentinfoptrvec)[j]->gender<<"\t"<<(*stduentinfoptrvec)[j]->age<<"\t"<<(*stduentinfoptrvec)[j]->is_absent<<"\t"<StudentInfoPtrVec studentinfoptrvec;char* p_char_1=NULL;p_char_1=new char[100];strcpy(p_char_1,"Micheal");StudentInfo* p_student_1=new StudentInfo;p_student_1->school_name=p_char_1;p_student_1->gender='m';p_student_1->age=18;p_student_1->is_absent=false;studentinfoptrvec.push_back(p_student_1);char* p_char_2=NULL;p_char_2=new char[100];strcpy(p_char_2,"Cherry");StudentInfo* p_student_2=new StudentInfo;p_student_2->school_name=p_char_2;p_student_2->gender='f';p_student_2->age=16;p_student_2->is_absent=false;studentinfoptrvec.push_back(p_student_2);print(&studentinfoptrvec);delete p_char_1;delete p_student_1;delete p_char_2;delete p_student_2;return 0;/*也可以这样释放内存*///我们要释放内存,自己new的就要自己释放,否则会造成内存泄漏;
std:vectoriterator pos:
for(pos =studentinfoptrvec.begin(:pos !=studentinfoptrvec.end();++pos)
delete(*pos);
}

p_student_2;
return 0;

/*也可以这样释放内存*///我们要释放内存,自己new的就要自己释放,否则会造成内存泄漏;

std:vectoriterator pos:
for(pos =studentinfoptrvec.begin(:pos !=studentinfoptrvec.end();++pos)
delete(*pos);
}


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t0GfGth7-1668872304536)(https://raw.githubusercontent.com/Ding-yixia/Typora/master/image-20221117232144015.png)]

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...