C++ auto类型说明符
编程时常常需要把表达式的值赋给变量,这就要求在声明变量的时候清楚知道表达式的类型。然而要做到这一点并非那么容易,有时候甚至根本做不到。为了解决这个问题,C++11标准引入了auto类型说明符,用它就能让编译器替我们去分析表达式所属的类型。
与原来那些只对应一种特定类型的说明符不同,auto让编译器通过初值来推算变量类型。显然,auto定义的变量必须要有初始值。
使用auto具有以下几点好处:
可靠性:如果表达式的类型发生更改(包括函数返回值发生更改的情况),它也能工作。
性能:确保将不会进行转换。
可用性:不必担心类型名称拼写困难和拼写有误。
效率:代码会变得更高效。
autoitem=val1+val2;//由val1和val2相加的结果推断出item的类型 autoi=0,*p=&i;//i是整数,p是整型指针
使用auto能在一条语句中声明多个变量。但是一条声明语句只能有一个基本数据类型,所以该语句中所有变量的初始基本数据类型都必须一致:
autosz=0,pi=3.14;//Error!
编译器推断出的auto类型有时候和初始值的类型并不完全一样,编译器会适当地改变结果类型使其更符合初始化规则,例如:
使用auto会删除引用
intcount=10; int&countRef=count; automyAuto=countRef; countRef=11; cout<<count<<"";//print11 myAuto=12; cout<<count<<endl;//print11
你可能会认为myAuto是一个int引用,但它不是。它只是一个int,因为输出为1111,而不是1112;如果auto尚未删除此引用,则会出现此情况。
const限定符
先引入一种表述:顶层const表示指针本身是个常量,底层const表示指针所指的对象是一个常量。一般auto会忽略掉顶层const,同时底层const则会保留下来,例如:
inti=0; constintci=i,&cr=ci; autob=ci;//b是一个整数(ci的顶层const特性被忽略掉) autoc=cr;//c是一个整数(cr是ci的别名,ci本身是一个顶层const) autod=&i;//d是一个整型指针(整数的地址就是指向整数的指针) autoe=&ci;//e是一个指向整数常量的指针(对常量对象取地址是一种底层const)
如果希望推断出的auto类型是一个顶层const,需要明确指出:
constautof=ci;//ci的推演类型是int,f是constint类型
还可以将引用的类型设置为auto,此时原来的初始化规则仍然适用:
auto&g=ci;//g是一个整型常量引用,绑定到ci auto&h=42;//Error:不能为非常量引用绑定字面值 constauto&j=42;//OK:可以为常量引用绑定字面值
切记,符号*和&只从属于某个声明,而非基本数据类型的一部分,因此初始值必须是同一类型:
autok=ci,&l=i;//k是整数,l是整型引用 auto&m=ci,*p=&ci;//m是对整型常量的引用,p是指向整型常量的指针 auto&n=i,*p2=&ci;//Error:i的类型是int,而&ci的类型是constint
附上更多示例代码:
下面的声明等效。在第一个语句中,将变量j声明为类型int。在第二个语句中,将变量k推导为类型int,因为初始化表达式(0)是整数
intj=0;//Variablejisexplicitlytypeint. autok=0;//Variablekisimplicitlytypeintbecause0isaninteger.
以下声明等效,但第二个声明比第一个更简单。使用auto关键字的最令人信服的一个原因是简单
map<int,list<string>>::iteratori=m.begin(); autoi=m.begin();
使用iter和elem启动循环时
#include<deque> usingnamespacestd; intmain() { deque<double>dqDoubleData(10,0.1); for(autoiter=dqDoubleData.begin();iter!=dqDoubleData.end();++iter) {/*...*/} //preferrange-forloopswiththefollowinginformationinmind //(thisappliestoanyrange-forwithauto,notjustdeque) for(autoelem:dqDoubleData)//COPIESelements,notmuchbetterthanthepreviousexamples {/*...*/} for(auto&elem:dqDoubleData)//observesand/ormodifieselementsIN-PLACE {/*...*/} for(constauto&elem:dqDoubleData)//observeselementsIN-PLACE {/*...*/} }
下面的代码片段使用new运算符和指针声明来声明指针
doublex=12.34; auto*y=newauto(x),**z=newauto(&x);
下一个代码片段在每个声明语句中声明多个符号。请注意,每个语句中的所有符号将解析为同一类型。
autox=1,*y=&x,**z=&y;//Resolvestoint. autoa(2.01),*b(&a);//Resolvestodouble. autoc='a',*d(&c);//Resolvestochar. autom=1,&n=m;//Resolvestoint.
此代码片段使用条件运算符(?:)将变量x声明为值为200的整数:
intv1=100,v2=200; autox=v1>v2?v1:v2;
下面的代码片段将变量x初始化为类型int,将变量y初始化对类型constint的引用,将变量fp初始化为指向返回类型int的函数的指针。
intf(intx){returnx;} intmain() { autox=f(0); constauto&y=f(1); int(*p)(intx); p=f; autofp=p; //... }