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