C++日记——Day5:迭代器、begin()/end(),rbegin()/rend()、迭代器失效、const_iterator

迭代器简介

迭代器是一种遍历容器内元素的一种数据类型,这种数据类型感觉有点像指针,我们理解的时候可以理解为欸带起用来指向容器中某个元素。

string,vector,[],很少用[],更常用的访问方式是迭代器(更通用)。

通过迭代器,我们就可以读容器中的元素值,读string中的每个字符,还可以修改某个迭代器所指向的元素值。

 

容器的迭代器类型

vector v{1, 2 ,3};
vector::iterator iter; //定义了一个迭代器,也必须是vector
//把整个的 vector::iterator 理解成一个类型,这种类型专门应用于迭代器。
//当我们用这个类型定义变量的时候,这个变量就是一个迭代器,这里iter就是个迭代器。

 

迭代器的begin()/end()操作,反向迭代器rbgin()/rend操作。

//begin()/end() 用来返回迭代类型。 rbegin()/rend()用来返回迭代类型。

1、begin()返回一个迭代器类型

iter = iv.begin(); //如果容器中有元素,则begin返回迭代器,指向容器的第一个元素相当于iv[0]

2、end():返回的是一个迭代器类型,返回的迭代器指向的是并不是末端元素,而是末端元素的后边,我们就理解成指向的是一个不存在的元素。

iter = iv.end(); 

C++日记——Day5:迭代器、begin()/end(),rbegin()/rend()、迭代器失效、const_iterator_第1张图片

 3、如果一个容器为空的话那么begin和end返回的迭代器就相同。

vector i {1, 2, 3, 4};

vector::iterator iter_begin;
vector::iterator iter_end;
iter_begin = i.begin();
iter_end = i.end();

4、通用的访问方法

vector i {1, 2, 3, 4};
for (vector::iterator iter = i.begin; iter != i.end(); iter++){
    cout << *iter << endl;
}

//反向迭代器
for (vector::reverse_iterator riter = i.rbegin; iter != i.rend(); iter++){
    cout << *riter << endl;
}

 反向迭代器原理

C++日记——Day5:迭代器、begin()/end(),rbegin()/rend()、迭代器失效、const_iterator_第2张图片

 

迭代器运算符

*iter:返回迭代器iter所指向的元素引用。必须要保证中灌迭代器指向的是有效的元素,不能指向end,因为end是末端元素后边,也就是一个不存在的元素。

iter++:指向当前迭代器的下一个元素。已经指向end后就不能在++

iter--:指向容器中的上一个元素,指向begin时不能再--

iter1 == iter2: iter1 != iter2,判断两个迭代器是否相等,否则就不等。

struct student { int num;};

vector sv;
student stu;
stu.num = 10;
sv.push_back(stu);

vector::iterator iter;
iter = sv.begin();
cout << (*iter).num << endl;
cout << iter->num << endl;

 

const_iterator迭代器:const:常量,const_iterator迭代器,表示值不能改变的意思,这里的值不能改变表示这个迭代器指向的元素值不能改变,而不是这个迭代器本身不能改变。所以这个迭代器只能读取元素,不能通过这个迭代器改写容器中的元素

const vector i {1, 2, 3, 4};

vector::const_interator iter; //常量容器必须用常量迭代器读取

for (iter = i.begin; iter != i.end(); iter++){ //可以
    cout << *iter << endl;
}

//-----------------------------------------------------------------------

vector::interator iter; //常量容器必须用常量迭代器读取

for (iter = i.begin; iter != i.end(); iter++){ //报错
    cout << *iter << endl;
}

//-----------------------------------------------------------------------

vector i {1, 2, 3, 4};

vector::const_interator iter; //常量容器必须用常量迭代器读取

for (iter = i.begin; iter != i.end(); iter++){ //可以
    *iter = 4; // 报错,常量迭代器只能读取容器数据,不能修改
    cout << *iter << endl;
}

 

cbegin()和cend(),和begin,end类似。cbegin与cend返回的都是常量迭代器。

for (auto iter = iv.cbegin(), iter != iv.cend(), iter++){
    *iter = 4;//报错
}

 

迭代器失效问题

vector vecvalue{1, 2, 3, 4};
for(auto v: vecvalue){

}

再操作迭代器过程中千万不要改变,也就是不要增加或者删除vector中的元素。往容器中增加或者删除元素,可能导致迭代器失效也就是不能再代表容器中的任何元素,一旦失效,就等与犯了严重的错误,很多情况下程序会直接崩溃报错。

防止迭代器失效最有效的方法就是修改后break出来,重新生成迭代

 

如何防止迭代器失效

防止迭代器失效要具体查找每种结构的构造方法。

vector vec{1, 2, 3, 4};

vector::iterator beg = vec.begin();
auto end = vec.end();
int icont = 0;

while( beg != vec.end() ){       //每次更新end,防止迭代器失效
    vec.insert(beg, 80+icont);
    icont++;
    if(icont > 5){
        break;
    }
    beg++;
}

 

释放vector

vector iv = {1, 2, 3};

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

上面的写法报错;

vector iv = {1, 2, 3};
auto beg = iv.begin();

while (iter ! = iv.end()){
    iter = iv.erase(iter);
}

while (!iv.empty()){
    vector::iterator iter = iv.begin();
    iv.erase(iter);
}

 

样例:

class conf {
public:
	char item_name[40];
	char item_content[100];
};

char *get_content(vector conf_list, const char *pitem) {
	vector::iterator conf_item;
	for (conf_item = conf_list.begin(); conf_item != conf_list.end(); conf_item++) {
		if (_stricmp((*conf_item)->item_name, pitem) == 0) {
			return (*conf_item)->item_content;
		}
		cout << (*conf_item)->item_name << endl;
	}
	return nullptr;
}

int main()
{
	conf *conf1 = new conf;
	conf *conf2 = new conf;

	strcpy_s(conf1->item_name, sizeof(conf1->item_name), "ServerName");
	strcpy_s(conf1->item_content, sizeof(conf1->item_content), "1区");

	strcpy_s(conf2->item_name, sizeof(conf2->item_name), "ServerID");
	strcpy_s(conf2->item_content, sizeof(conf2->item_content), "1001");

	vector vec{conf1,conf2};

	char *p = get_content(vec, "ServerID");

	if (p != nullptr) {
		cout << p << endl;
	}
	else
	{
		cout << "not match" << endl;
	}

	vector::iterator pos;
	for (pos = vec.begin(); pos != vec.end(); pos++) {
		delete (*pos);
	}
	vec.clear();
}

 

你可能感兴趣的:(C++日记)