迭代器简介
迭代器是一种遍历容器内元素的一种数据类型,这种数据类型感觉有点像指针,我们理解的时候可以理解为欸带起用来指向容器中某个元素。
string,vector,[],很少用[],更常用的访问方式是迭代器(更通用)。
通过迭代器,我们就可以读容器中的元素值,读string中的每个字符,还可以修改某个迭代器所指向的元素值。
容器的迭代器类型
vector<int> v{1, 2 ,3};
vector<int>::iterator iter; //定义了一个迭代器,也必须是vector<int>
//把整个的 vector<int>::iterator 理解成一个类型,这种类型专门应用于迭代器。
//当我们用这个类型定义变量的时候,这个变量就是一个迭代器,这里iter就是个迭代器。
迭代器的begin()/end()操作,反向迭代器rbgin()/rend操作。
//begin()/end() 用来返回迭代类型。 rbegin()/rend()用来返回迭代类型。
1、begin()返回一个迭代器类型
iter = iv.begin(); //如果容器中有元素,则begin返回迭代器,指向容器的第一个元素相当于iv[0]
2、end():返回的是一个迭代器类型,返回的迭代器指向的是并不是末端元素,而是末端元素的后边,我们就理解成指向的是一个不存在的元素。
iter = iv.end();
3、如果一个容器为空的话那么begin和end返回的迭代器就相同。
vector<int> i {1, 2, 3, 4};
vector<int>::iterator iter_begin;
vector<int>::iterator iter_end;
iter_begin = i.begin();
iter_end = i.end();
4、通用的访问方法
vector<int> i {1, 2, 3, 4};
for (vector<int>::iterator iter = i.begin; iter != i.end(); iter++){
cout << *iter << endl;
}
//反向迭代器
for (vector<int>::reverse_iterator riter = i.rbegin; iter != i.rend(); iter++){
cout << *riter << endl;
}
反向迭代器原理
迭代器运算符
*iter:返回迭代器iter所指向的元素引用。必须要保证中灌迭代器指向的是有效的元素,不能指向end,因为end是末端元素后边,也就是一个不存在的元素。
iter++:指向当前迭代器的下一个元素。已经指向end后就不能在++
iter--:指向容器中的上一个元素,指向begin时不能再--
iter1 == iter2: iter1 != iter2,判断两个迭代器是否相等,否则就不等。
struct student { int num;};
vector<student> sv;
student stu;
stu.num = 10;
sv.push_back(stu);
vector<student>::iterator iter;
iter = sv.begin();
cout << (*iter).num << endl;
cout << iter->num << endl;
const_iterator迭代器:const:常量,const_iterator迭代器,表示值不能改变的意思,这里的值不能改变表示这个迭代器指向的元素值不能改变,而不是这个迭代器本身不能改变。所以这个迭代器只能读取元素,不能通过这个迭代器改写容器中的元素。
const vector<int> i {1, 2, 3, 4};
vector<int>::const_interator iter; //常量容器必须用常量迭代器读取
for (iter = i.begin; iter != i.end(); iter++){ //可以
cout << *iter << endl;
}
//-----------------------------------------------------------------------
vector<int>::interator iter; //常量容器必须用常量迭代器读取
for (iter = i.begin; iter != i.end(); iter++){ //报错
cout << *iter << endl;
}
//-----------------------------------------------------------------------
vector<int> i {1, 2, 3, 4};
vector<int>::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<int> vecvalue{1, 2, 3, 4};
for(auto v: vecvalue){
}
再操作迭代器过程中千万不要改变,也就是不要增加或者删除vector中的元素。往容器中增加或者删除元素,可能导致迭代器失效也就是不能再代表容器中的任何元素,一旦失效,就等与犯了严重的错误,很多情况下程序会直接崩溃报错。
防止迭代器失效最有效的方法就是修改后break出来,重新生成迭代
如何防止迭代器失效
防止迭代器失效要具体查找每种结构的构造方法。
vector<int> vec{1, 2, 3, 4};
vector<int>::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<int> iv = {1, 2, 3};
for(vector<int>::iterator iter = iv.begin(); iter != iv.end; ++iter){
iv.erase(iter); //erase函数,移除iter位置上的元素,返回下一个位置元素;
}
上面的写法报错;
vector<int> iv = {1, 2, 3};
auto beg = iv.begin();
while (iter ! = iv.end()){
iter = iv.erase(iter);
}
while (!iv.empty()){
vector<int>::iterator iter = iv.begin();
iv.erase(iter);
}
样例:
class conf {
public:
char item_name[40];
char item_content[100];
};
char *get_content(vector<conf *> conf_list, const char *pitem) {
vector<conf *>::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<conf *> vec{conf1,conf2};
char *p = get_content(vec, "ServerID");
if (p != nullptr) {
cout << p << endl;
}
else
{
cout << "not match" << endl;
}
vector<conf *>::iterator pos;
for (pos = vec.begin(); pos != vec.end(); pos++) {
delete (*pos);
}
vec.clear();
}