迭代器精彩演绎,失效分析及弥补、实战

025迭代器常见操作

#include<iostream>
#include<cstdlib>
#include<string>
#include<vector>

using namespace std;


struct  Student
{
	int age;
	int number;
};

int main(void)
{
	vector<int>Number1 = { 100,200,300,400 };
	//定义迭代器变量
	vector<int>::iterator iter;	//	vector<int>::iterator就是变量类型,iter是变量名字。
	//每一种容器中都会定义一个iterator的成员,是固定的
	//大家在理解的时候vector<int>::iterator就是一种类型,这种类型就是迭代器类型。用这个数据类型定义一个变量就是迭代器

	//迭代器begin() end()操作
	iter = Number1.begin();	//如果容器中有元素,返回的是迭代器,指向容器中的第一个元素。
	//相当于iter指向编号为0的元素
	iter = Number1.end();	//返回的并不是最后一个元素,而是最后一个元素的下一个位置。理解为end()指向不存在的一个位置

	//如果是一个空容器,那么begin()和end()返回的就相同了
	vector<int>Number2;
	vector<int>::iterator beginIter = Number2.begin();
	vector<int>::iterator endIter = Number2.end();
	if (beginIter==endIter)	//验证了,指向同一个位置
	{
		cout << "两个迭代器指向同一个位置" << endl;
	}

	
	//遍历输出容器中的内容
	for (vector<int>::iterator iter2=Number1.begin();iter2!=Number1.end();iter2++)
	{
		cout << *iter2 << endl;	//迭代器可以当做指针来看待  100 200 300 400
	}

	//反向访问,先访问最后一个元素--反向迭代器(逆向迭代器)
	/*
	 * rbegin()返回一个反向迭代器,指向反向迭代器的第一个元素
	 * rend() 返回一个反向迭代器,指向反向迭代器的最后一个元素的下一个元素
	 * 
	 */
	//反向输出Number1中的内容
	for (vector<int>::reverse_iterator rIter3=Number1.rbegin();rIter3!=Number1.rend();rIter3++)
	{
		cout << *rIter3 << endl;	//400 300 200 100
	}

	//容器中存储结构体,并遍历输出---输出成员
	vector<Student> stuVector;
	Student myStu = { 12,1000 };
	stuVector.push_back(myStu);	//复制进容器后,就是两个无关的东西,每个都有自己的内存
	//输出结构体中的内容
	vector<Student>::iterator iter04 = stuVector.begin();
	cout << (*iter04).number << endl;
	cout << iter04->number << endl;


	//const_iterator迭代器--当容器被定义为常量容器的时候,必须使用常量迭代器
	const vector<int>Number04 = { 0,1,2,3,4 };
	for (vector<int>::const_iterator cIter = Number04.begin();cIter!=Number04.end();cIter++)
	{
		//*cIter = 12;	//不可以修改
		cout << *cIter << endl;	//可以正常读	
	}
	
	//(5)cbegin cend
	for (auto iter05=Number04.cbegin();iter05!=Number04.end();iter05++)
	{
		//*iter05 = 6;//error
		cout << *iter05 << endl;	
	}


	//(6)复习范围for语句内部就是使用迭代器实现的
	vector<int>Number06 = { 1,2,3,4,5 };
	for (auto x:Number06)
	{
		cout << x << endl;
	}
	//等价于迭代器
	for (auto beg=Number06.begin(),end1=Number06.end();beg!=end1;beg++)
	{
		cout << *beg << endl;
	}

	
	system("pause");
	return 0;
}

/*
* (1)迭代器简介
*	vector是一个容器,迭代器就是一种遍历容器内元素的数据类型。这种数据类型像指针。
*	我们理解迭代器就指向容器中的某个元素。
*
*	如vector和string中可以通过下标运算符[]来访问元素,其实在c++中很少通过下标来访问,一般通过迭代器来访问。
*	通过迭代器,我们可以读容器中的元素值,读string中的每个字符,还可以修改某个迭代器所指向的元素值。迭代器也有++  --等操作
*	尽量使用迭代器来访问迭代器中的元素。
*
*2)容器的迭代器类型
*	每一种容器中都会定义一个iterator的成员,是固定的
*
*	迭代器begin() end() rbegin() rend()操作
*		begin() end()用于返回迭代类型,
*		1.begin()返回一个迭代器类型,理解为返回一个迭代器
*		2.end()并不指向容器中的任何元素,起的作用实际上是标记作用。
*		3.遍历输出容器中的内容for
*
*3)迭代器运算符
*	*iter--返回迭代器iter所指向的元素的引用。必须要保证迭代器指向的是有效的元素。不能指向end()
*	++iter  iter++ 迭代器指向下一个元素。指向end()不能再++
*	--iter iter--指向容器中的上一个元素
*	iter1==iter2 != 判断两个迭代器是否相等===
*
*4)const_iterator迭代器--一般表示常量迭代器,表示不能通过迭代器去修改容器中元素的值。迭代器本身的指向是可以改变的。
*	感觉起来有点像常量指针。
*5cbegin() cend()函数 返回的都是常量迭代器,与是否是常量容器无关
*

*	
*	
*/

026迭代器失效灾难程序演示

#include<iostream>
#include<cstdlib>
#include<string>
#include<vector>
using namespace std;



int main(void)
{
	vector<int> Number1{ 1,2,3,4,5 };
	auto beg = Number1.begin();
	auto end = Number1.end();
	while (beg!=end)
	{
		cout << *beg << endl;
		Number1.insert(beg, 1000);	//插入元素,第一个为元素位置,是一个迭代器位置,2为元素的值
		//这条语句会导致迭代器失效,具体哪个迭代器失效,取决于容器的实现原理,我们不去详细研究。最明智的做法就是
		//一插入数据就立刻break出来,重新建立迭代器,重新循环遍历
		break;
		++beg;
	}
	//前面插入数据,重新循环遍历,前面的迭代器已经失效
	beg = Number1.begin();
	end = Number1.end();
	while (beg != end)
	{
		cout << *beg << endl;
		++beg;
	}


	//如果不使用break方法,就每次更新end()
	auto beg2 = Number1.begin();
	int iCount = 0;
	while(beg2!=Number1.end())	//每次更新,放置end失效
	{
		beg2 = Number1.insert(beg2, iCount + 80);//查看每次插入结果
		iCount++;
		if (iCount>10)
		{
			break;
		}
		++beg2;
	}
	for(beg2=Number1.begin();beg2!=Number1.end();beg2++)
	{
		cout << *beg2 << endl;
	}



	
	system("pause");
	return 0;
}

/*
* (1)
* *()6)迭代器失效问题
*	回顾范围for循环--使用迭代器实现
*	在操作迭代器的过程中,千万不要改变vector容器的容量。不要增加或者删除vector中的元素的个数
*	增加或者删除元素,这种操作可能导致指向容器的迭代器失效。失效就表示不能再代表任何容器中的元素。一旦使用失效的东西,
*	就等于犯了园中的程序错误。在很多情况下,程序会直接崩溃。list map中都是顺序存储的,插入或删除元素都需要排序。
*	插入或者删除会导致种种迭代器失效。
*
*灾难程序演示1--
*迭代器改变了元素的个数,马上break出来
*/



灾难程序演示2

#include<iostream>
#include<cstdlib>
#include<string>
#include<vector>
using namespace std;



int main(void)
{
	vector<int> Number1{ 1,2,3,4,5 };
	auto beg = Number1.begin();
	auto end = Number1.end();


	for (;beg!=end;beg++)
	{
		//Number1.erase(beg);	//移除beg迭代器指向的元素,返回下一个元素的位置
		
	}

	//一个一个清除,每次计算end()的值--可以使用
	vector<int>::iterator iter = Number1.begin();
	while(iter!=Number1.end())
	{
		iter = Number1.erase(iter);
	}

	//另一种删除方法--每次指向开头,每次判断是否为空
	while (!Number1.empty())
	{
		auto iter2 = Number1.begin();
		Number1.erase(iter2);
	}


	
	system("pause");
	return 0;
}

/*
 *(1)灾难程序演示2
*/



028用迭代器遍历string类型数据

#include<iostream>
#include<cstdlib>
#include<string>
#include<vector>
#include <cctype>

using namespace std;

int main(void)
{
	string str("jisuanjizuochegnyuanli");
	for (auto iter=str.begin();iter!=str.end();iter++)
	{
		*iter = std::toupper((*iter));
	}
	cout << str << endl;


	
	system("pause");
	return 0;
}

/*
* (1)用迭代器变脸string类型数据
*/

029vector容器常用操作与内存释放

#include<iostream>
#include<cstdlib>
#include<string>
#include<vector>
//用于保存配置文件的结构体
struct Config
{
	char IterName[128];	//条目名字
	char ItemContent[128];	//条目内容
};
using namespace std;


//根据item查找content的内容
char* getInfo(vector<Config*>&conflist,char*pItem)
{
	for (auto pos=conflist.begin();pos!=conflist.end();pos++)
	{
		if (strcmp((*pos)->IterName,pItem)==0)
		{
			return (*pos)->ItemContent;
		}
	}
	return nullptr;
}


int main(void)
{
	Config*pConfig = new Config;
	strcpy_s(pConfig->IterName, sizeof(pConfig->IterName), "ServerName");
	strcpy_s(pConfig->ItemContent, sizeof(pConfig->ItemContent), "1区");

	Config*pConfig2 = new Config;
	strcpy_s(pConfig2->IterName, sizeof(pConfig2->IterName), "ServerID");
	strcpy_s(pConfig2->ItemContent, sizeof(pConfig2->ItemContent), "100000");

	vector<Config*>ConfList;
	ConfList.push_back(pConfig);	//元素0
	ConfList.push_back(pConfig2);	//元素1
	/*
	 * 注意:容器中存储指针类型,那么数据只存在一份,但是外面使用new创建的指针对象(pConfig pConfig2)和容器中
	 * 的元素0 元素1都是指向同一快内存空间。也就是说,两个指针指向同一块内存空间。
	 */
	//怎么根据item返回对应的content内容
	char*p_Tem = getInfo(ConfList, "ServerName");
	if (p_Tem!=nullptr)
	{
		cout << p_Tem << endl;	//1区域
	}

	//我们需要自己释放内存,自己new的就要自己释放,否则就会造成内存泄漏
	//每次遍历一次,就把容器中元素指向的内存空间释放但是容器中的元素不释放。
	for (vector<Config*>::iterator pos=ConfList.begin();pos!=ConfList.end();pos++)	
	{
		delete(*pos);//	容器中的元素本来就指针,pos相当于二级指针,所以*pos才是那个指针
	}
	ConfList.clear();	//这一操作可以没有,系统系统在运行结束自动清空容器
	
	system("pause");
	return 0;
}

/*
* (1)实践程序
* ServerName=1区 服务器名字
* ServerID=1000 服务器ID
*
*  Sunrise于东北电力大学第二教学楼1121实验室
*  2019年11月14日12:07:53
*  
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值