C++中迭代器

一、迭代器简介

  迭代器是一种遍历容器内元素的数据类型,这种数据类型有点像指针,理解时候可以理解为迭代器用来指向容器中的某个元素。
vector可以用[]来访问,但是更常用的访问方式是用迭代器。
通过迭代器,我们可以读容器中的元素值,读string中的每个字符,还可以修改某个迭代器所指向的元素值。
一般有容器都会有相关的迭代器list、map等。

二、容器的迭代器类型

vector <int> iv = {100,200,300};
vector<int>::iterator iter;//定义迭代器,也必须是vector<int>

理解时候可以把整个vector::iterator理解成一个类型,这个类型专门应用于迭代器。
当我们用这个类型定义一个变量时,这个变量就是个迭代器,这里iter这个变量就是个迭代器
三、迭代器begin()/end()操作,反向迭代器rbegin()/rend()操作
  begin()/end()用来返回迭代类型.rbegin()/rend()一样。

iter = iv.begin();//如果容器中有元素则begin返回的迭代器指向容器中第一个元素
iter = iv.end();//end返回末尾元素的后面一个元素

在这里插入图片描述
如果是一个空容器,那么begin()和end()返回的迭代器就相同。
用迭代器来遍历容器

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

using namespace std;
int main()
{
	vector<int> value{1,2,3,4};
	
	for (vector<int>::iterator iter = value.begin(); iter != value.end(); iter++)
	{
		cout << *iter << endl;
	}

	return 0;
}

结果

1
2
3
4

逆向迭代器:从后往前访问
在这里插入图片描述
rbegin():返回一个反向迭代器指向反向迭代器的第一个元素
rend();返回一个反向迭代器指向反向迭代器的最后一个元素的下一个位置(容器最开始元素的前一个位置)

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

using namespace std;
int main()
{
	vector<int> value{1,2,3,4};
	
	for (vector<int>::reverse_iterator riter = value.rbegin(); riter != value.rend(); riter++)
	{
		cout << *riter << endl;
	}

	return 0;
}

结果

4
3
2
1

四、迭代器运算符
*iter:返回迭代器iter所指向元素的引用。必须要保证这个迭代器指向是有效的容器元素,不能指向end(),因为end()是末端元素后边(不存在的一个元素)riter同理。
++iter;iter++;–iter;iter–;都遵循以上原则(不能指向不存在的元素)

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

using namespace std;

struct student
{
	int num;
};

int main()
{
	vector<student> sv;
	student mystu;
	mystu.num = 100;
	sv.push_back(mystu);//把对象mystu复制到sv容器中

	vector<student>::iterator iter;
	iter = sv.begin();//指向第一个元素
	cout << (*iter).num << endl;
	cout << iter->num << endl;
	
	return 0;
}
100
100

五、const_iterator迭代器
const_iterator迭代器表示迭代器指向的值不能改变,只能从迭代器中读元素。(iterator能读能写)


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

using namespace std;

int main()
{
	vector<int> iv{1,2,3,4};
	vector<int>::const_iterator iter;

	for (iter = iv.begin(); iter != iv.end(); iter++)
	{
		cout << *iter << endl;
	}
	
	return 0;
}

结果

1
2
3
4

如果是const vector iv{1,2,3,4};常量容器的话就必须用const_iterator来迭代。
5.1cbegin()和cend()操作
c++11引入的两个新函数cbegin()和cend(),跟begin,end类似。cbegin,cend,返回的都是常量迭代器

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

using namespace std;

int main()
{
	vector<int> iv{1,2,3,4};

	for (auto iter = iv.cbegin(); iter != iv.cend(); iter++)
	{
		cout << *iter << endl;
	}
	
	return 0;
}

与上面结果一样,既然返回的是常量迭代器那么与const_iterator一样不能进行赋值操作。
六、迭代器失效
回顾一下学习容器时的失效问题

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

using namespace std;

int main()
{
	vector<int> iv{1,2,3,4};

	for (auto vecitem: iv)
	{
		iv.push_back(88);
		cout << vecitem << endl;
	}
	
	return 0;
}
/*
	for(auto beg = iv.begin(), end = iv.end();beg != end; ++beg)
	{
		iv.push_back(88);
		cout << *beg <<endl;
	}
*/

结果

1
-572662307
-572662307
-572662307

注:在迭代器遍历时进行增/删操作与注释内容是等价的,在操作迭代器过程中,千万不要改变vector容器容量,也就是不要进行增删操作。增加或者删除操作可能会使指向容器的元素指针、引用、迭代器失效。程序可能直接崩溃。如果要进行增加或者删除操作要立即退出去。

for (auto beg = iv.begin(), end = iv.end(); beg != end; ++beg)
{
	iv.push_back(88);
	break;
}

for (auto beg = iv.begin(), end = iv.end(); beg != end; ++beg)
{
	iv.push_back(88);
	cout << *beg << endl;
}

如果想一直插入一定要做好处理,最好是做完操作立即break;

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

using namespace std;

int main()
{
	vector<int> iv{1,2,3,4};

	auto beg = iv.begin();
	int icount=0;
	while (beg != iv.end())//每次更新end防止end失效
	{
		beg = iv.insert(beg, icount++);//insert参数1插入位置,参数2插入元素
		if (icount > 10)
			break;
		++beg;
	}
	beg = iv.begin();
	auto end = iv.end();
	while (beg != end)
	{
		cout << *beg << endl;
		++beg;
	}

	return 0;
}
0
1
2
3
4
5
6
7
8
9
10
1
2
3
4

在程序结束前我们可能会释放掉容器里面内容看如下代码(错误的方法)

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

using namespace std;

int main()
{
	vector<int> iv{1,2,3,4};

	auto beg = iv.begin();
	for (auto iter = iv.begin(); iter != iv.end(); ++iter)
	{
		iv.erase(iter);//erase:移除iter位置上的元素,返回下一个元素位置
	}

	return 0;
}

当这段程序执行时直接崩溃,不用想,问题出在迭代器上,正确做法如下

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

using namespace std;

int main()
{
	vector<int> iv{1,2,3,4};

	auto iter = iv.begin();
	while (iter != iv.end())
	{
		iter = iv.erase(iter);
	}
/*
while (!iv.empty())//判断是否为空
{
	auto iter = iv.begin();//因为不为空,所以返回begin没问题
	iv.erase(iter);//删除位置上的元素
}
*/
	return 0;
}

以上两种方法是一个一个清空,直接清空也可以使用iv.clear();方法
七、范例演示
7.1、用迭代器变量一下string类型数据

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

using namespace std;

int main()
{
	string str("I Love China!");

	for (auto iter = str.begin(); iter != str.end(); ++iter)
	{
		*iter = toupper(*iter);//转成大写
	}
	cout << str << endl;

	return 0;
}
I LOVE CHINA!

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

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

using namespace std;

struct conf
{
	char itemname[40];
	char itemcontent[100];
};

char *getinfo(vector<conf *>&conflist, char *pitem)//返回字符串
{
	for (auto iter = conflist.begin(); iter != conflist.end(); ++iter)
	{
		if (_stricmp((*iter)->itemname, pitem) == 0)//根据名字返回内容
		{
			return (*iter)->itemcontent;
		}
	}
	return nullptr;//没有找到返回空
}

int main()
{
	//ServerName = 1区//表示服务器名称
	//ServerID =1000//表示服务器ID
	conf *pconf1 = new conf;
	strcpy_s(pconf1->itemname, sizeof(pconf1->itemname), "ServerName");
	strcpy_s(pconf1->itemcontent, sizeof(pconf1->itemcontent), "1区");

	conf *pconf2 = new conf;
	strcpy_s(pconf2->itemname, sizeof(pconf2->itemname), "ServerID");
	strcpy_s(pconf2->itemcontent, sizeof(pconf2->itemcontent), "1000");

	vector<conf *> conflist;
	conflist.push_back(pconf1);
	conflist.push_back(pconf2);

	char *p_temp = getinfo(conflist, "ServerName");
	if (p_temp != nullptr)
	{
		cout << p_temp << endl;//1区
	}
	//自己new的自己释放,否则会有内存泄漏
	std::vector<conf *>::iterator pos;
	for(pos = conflist.begin(); pos != conflist.end(); ++pos)
	{
		delete (*pos);//删除图中蓝色内存,容器里面指向的内存无效了
	}

	conflist.clear();//列表指针指向的内存释放掉了,把列表也清空一下

	return 0;
}

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值