迭代器 iterator

本文介绍了C++中的迭代器概念,作为遍历容器元素的工具,迭代器支持读取和修改元素值,并可通过++、--操作移动。文章通过示例展示了如何使用begin()和end()获取迭代器,以及反向迭代器rbegin()和rend()的用法。还提到了const_iterator用于只读访问,以及迭代器在插入和删除元素后的失效问题。最后,通过一个示例展示了在vector容器中使用迭代器查找和释放内存的操作。

迭代器简介

  • 迭代器是一种遍历容器内元素的数据类型。(这种数据类型有点像指针,可以将迭代器理解为是用来指向容器内的某个元素的)
  • string可以用“[ ]”来访问string字符串内的字符,vector也可以通过“[ ]”来访问vector中的元素。但C++中一般采用迭代器来访问它们。除了vector容器外,C++标准库中还有好几种其他种类的容器(如:listmap等),均可使用迭代器来访问它们。string不是容器,但也支持用迭代器来遍历。

通过迭代器,可以读取容器中的元素值,修改容器中某个迭代器所代表(指向)的元素值。此外,迭代器可以像指针一样——通过++- -等运算从容器中的一个元素移动到另一个元素。

注:有很多容器并不支持“[ ]”来访问,但容器都支持迭代器来访问。


举例说明:
vector<int> myvec = {10,20,30,40};
vector<int>::iterator myiter // 定义了一个迭代器myiter;
iterator是每个容器里面都定义了的一个成员(类型名),这个名字是固定的。


迭代器begin/end 、反向迭代器rbegin/rend

每一种容器(如vector)都定义了一个叫begin()的成员函数和一个叫end()的成员函数,这两个成员函数正好用来返回迭代器类型。

  1. begin() 如果容器中有元素,返回的迭代器指向容器中的第一个元素。
    myiter = myvec.begin() // 相当于myiter代表着元素myvec[0]

  2. end() 返回的迭代器指向的并不是末端元素,而是末端元素的后面。
    myiter = myvec.begin() // 指向末端元素后面,该元素并不存在

  3. 如果容器为空,则begin()返回的迭代器和end()返回的迭代器相同。

迭代器指向示意图
如果想从后面往前遍历一个容器,可以使用反向迭代器。即使用rbegin()成员函数和rend()成员函数。

  1. rbegin() 返回一个反向迭代器,指向容器中最后一个元素。

  2. rend() 返回一个反向迭代器,指向容器中第一个元素前面的位置。

反向迭代器指向示意图

const_iterator 迭代器

const表示常量,其值不能改变。这里的值不能改变指的是迭代器指向的元素值不能改变,并不表示迭代器本身不能改变,该迭代器本身是能改变的。

该迭代器只能从容器中读取元素,不能通过该迭代器改变容器中元素的值。所以,const_iterator 更像一个常量指针,而 iterator 迭代器是能读能写的。

	const vector<int>myiv = { 10,20,30,40 };
	vector<int>::const_iterator myiter;
	for ( myiter = myiv.begin(); myiter != myiv.end(); myiter++)
	{	//这里的begin()和end()返回的是const_iterator
		//返回的是iterator还是const_iteraor,取决于对象容器是否是const对象
		cout << *myiter << endl;
	}

C++11引入了两个新的成员函数 cbegin()cend() 。不管容器是否是常量容器,cbegin()cend() 返回的都是const_iterator

迭代器失效

for循环中,增删容器中的元素都会导致迭代器失效。如果在一个使用了迭代器的循环中插入元素到容器中,那么只插入一个元素后就应该立即跳出循环体。



举例:vector容器常用操作和内存释放
存在一个配置项:
ServerName = 1区
ServerID =10000

#include<iostream>
#include<vector>
using namespace std;
struct conf
{
	char itemname[40];
	char itemcontent[100];
};
char* getinfo(vector<conf*>& conflist, const char* pitem)
{
	for (auto pos = conflist.begin(); pos != conflist.end(); pos++)
	{
		if ( _stricmp( (*pos)->itemname , pitem ) == 0 )
		{
			return ( *pos) -> itemcontent;
		}
	}
	return nullptr;
}
int main(void)
{
	conf* p_conf1 = new conf;
	strcpy_s(p_conf1->itemname, sizeof(p_conf1->itemname), "ServerName");
	strcpy_s(p_conf1->itemcontent, sizeof(p_conf1->itemcontent), "1区");

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

	vector<conf*> conflist;
	conflist.push_back(p_conf1);
	conflist.push_back(p_conf2);

	char* p_tmp = getinfo(conflist, "ServerName");
	//char* p_tmp = getinfo(conflist, "ServerID");
	if (p_tmp != nullptr)
	{
		cout << p_tmp << endl;
	}
	//要释放内存,自己new就要自己delete,否则会造成内存泄漏
	vector<conf*>::iterator pos;
	for  (pos = conflist.begin(); pos != conflist.end(); pos++)
	{
		//这里并没有破坏迭代器,因为没有往conflist里增加或删除元素,
		//只是删除迭代器里元素所指向的由我们自己分配的内存
		delete (*pos); 
	}
	//.clear()这个可以不要,因为容器里的内容,在容器失效后系统会自动释放
	conflist.clear();

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值