【C++初阶】auto关键字、范围for循环与迭代器详解
1.auto关键字在早期的C/C中auto的含义是使用auto修饰的变量是具有自动存储器的局部变量后来这个不重要了。在C11中标准委员会将auto作为一个新的类型指示符来指示编译器auto声明的变量必须由编译器在编译时期推导而得用auto声明指针类型时用auto和auto*没有任何区别但是auto声明引用类型时必须加当在同一行声明多个变量时这些变量必须是同一个类型否则编译器会报错。因为编译器实际上只对第一个类型进行推导然后用推导出来的类型定义其他变量auto不能做函数的参数可以做返回值但建议谨慎使用auto不能直接用来声明数组#includeiostreamusingnamespacestd;intfunc1(){return10;}//// auto不能做参数会报错//void func2(auto a) {//}// auto可以做返回值但建议谨慎使用autofunc3(){return3;}intmain(){inta10;autoba;autoca;autodfunc1();// 编译报错“e”: 类型包含“auto”的符号必须具有初始值设定项//auto e;// typeid(b).name()用来打印变量的类型couttypeid(b).name()endl;couttypeid(c).name()endl;couttypeid(d).name()endl;intx10;autoyx;auto*zx;automx;couttypeid(x).name()endl;couttypeid(y).name()endl;couttypeid(z).name()endl;autoaa1,bb2;// 编译报错在声明符列表中“auto”必须始终推导为同一类型//auto cc 3, dd 4.0;// 编译报错“auto []”: 数组不能具有其中包含“auto”的元素类型//auto array[] { 4,5,6 };return0;}使用auto简化代码#includeiostream#includestring#includemapusingnamespacestd;intmain(){std::mapstd::string,std::stringdict{{apple,苹果},{orange,橙子},{pear,梨}};// 使用迭代器遍历时如果类型名很长可以使用auto自动推导起到简化代码的作用//std::mapstd::string, std::string::iterator it dict.begin();autoitdict.begin();while(it!dict.end()){coutit-first:it-secondendl;it;}return0;}2.范围for范围for适用于容器和数组对于一个有范围的集合遍历时可以使用范围for循环。for循环后的括号由冒号“:”分成两部分第一部分是范围内用于迭代的变量第二部分则表示被迭代的范围。自动迭代自动取数据自动判断结束。范围for可以作用到数组和容器对象上进行遍历范围for的底层是迭代器#includeiostream#includestringusingnamespacestd;intmain(){intarray[]{1,2,3,4,5};// C98的遍历for(inti0;isizeof(array)/sizeof(array[0]);i){array[i]*2;}for(inti0;isizeof(array)/sizeof(array[0]);i){coutarray[i]endl;}coutendl;// C11的遍历// 使用auto自动推导类型// 范围for自动赋值自动迭代自动判断结束// 底层是迭代器编译后替换为迭代器// 所用容器都支持范围for所有容器都支持迭代器for(autoe:array){e*2;}for(autoe:array){couteendl;}// ch相当于str中每个字符的拷贝是局部变量// 改变ch不会改变str的值// 将auto改为auto使用引用即可修改stringstr(hello world);for(autoch:str){coutch ;}coutendl;return0;}3.迭代器迭代器是⼀种对象它可以用来遍历容器中的元素迭代器的作用类似于指针或者数组下标。所有容器都有自己的迭代器且用法相似访问迭代器的数据需要解引用迭代器体现了封装的思想屏蔽了底层的实现细节提供了统一、类似的访问容器的方式不需要关心容器底层结构和实现细节begin()和end()以string为例begin()返回指向字符串第一个字符的迭代器需要使用一个迭代器变量来接受end()返回指向字符串最后一个字符下一个位置的迭代器该位置不属于字符串string中begin()和end()返回的迭代器的类型是string::iterator迭代器可以进行大小比较也可以进行或者-整数运算同一个容器的两个迭代器可以相减相减结果的绝对值是两个迭代器中间元素个数#includeiostream#includestringusingnamespacestd;intmain(){string sabcdef;string::iterator it1s.begin();string::iterator it2s.end();// 迭代器可以进行大小比较也可以进行 或者 - 整数运算cout(it1it2)endl;// 同一个容器的两个迭代器可以相减相减结果的绝对值是两个迭代器中间元素个数coutit1-it2endl;return0;}运行结果正序遍历#includeiostream#includestringusingnamespacestd;intmain(){string sabcdef;// auto it 是让编译器自动推导it的类型for(autoits.begin();it!s.end();it){cout*it ;}coutendl;// string::iterator 是正向迭代器类型// string::iterator it 是直接创建迭代器it是针对字符串的迭代器for(string::iterator its.begin();it!s.end();it){cout*it ;}return0;}逆序遍历#includeiostream#includestringusingnamespacestd;intmain(){string sabcdef;for(string::iterator its.end()-1;its.begin();--it){cout*it ;}return0;}通过迭代器找到元素后改变迭代器指向的元素是可以直接改变字符串内容的。#includeiostream#includestringusingnamespacestd;intmain(){string strabcdef;coutstrendl;for(string::iterator itstr.begin();it!str.end();it){*itx;}coutstrendl;return0;}const变量使用const_iterator遍历类似于const int*rbegin()和rend()反向迭代器的类型reverse_iterator起始位置rbegin()结尾rend()反向迭代器遍历时用就可以倒着遍历const类型使用const_reverse_iterator使用reverse_iterator迭代器逆序遍历字符串#includeiostream#includestringusingnamespacestd;intmain(){string sabcdef;for(string::reverse_iterator its.rbegin();it!s.rend();it){cout*it ;}return0;}