auto
auto与decltype
均能自动推导变量类型,但两者在很多方面右有着许多不同。
auto是c++11新标准引入的类型说明符,它能让编译器自动分析表达式所属的类型,auto让编译器通过初始值来推算变量的类型。
使用auto能在一条语句中声明多个变量,一条声明语句只能有一个基本数据类型,所以该句中所有变量的初始基本数据类型都一样。
auto i = 0, *p = &i; // 正确;i是整数,p是整型指针
auto sz = 0, pi = 3.14; // 错误;sz和pi的类型不一致
auto一般会忽略顶层const
,保留底层const
。
const int ci = i, &cr = ci;
auto b = ci; // b是一个整数,b的值可以被改变(ci的顶层const被忽略了)
auto c = cr; // c是一个整数(cr是ci的别名,而此表达式中真正参与初始化的是引用对象的值,即ci的值)
auto d = &i; // d是一个整型指针,表达式右边对i取地址,故auto推导出d的类型为指针
auto e = &ci; // 表达式左边对ci取地址,ci是常量对象,其值不可改变,故不能通过对指向它的指针来改变ci的值,所以auto推导出e是一个指向常量的指针(底层const)
若希望auto保留顶层const
,需把const
写至auto前面:
const auto f = ci; // ci的推演类型是int,f是const int类型(顶层const)
decltype
c++11新标准引入了decltype
,它返回操作数了数据类型。在此过程中,编译器分析表达式得到它的值,却不实际计算表达式的值。
decltype(f()) sum = x; // sum的数据类型由f函数的返回值决定,但不实际运行计算f函数
decltype
处理顶层const
和引用的方式与auto有些许不同。如果decltype
使用的表达式是一个变量,则decltype
返回该变量的类型(包括顶层const
与引用):
const int ci = 0, &cj = ci;
decltype(ci) x = 0; // x的类型被推导为顶层const int
decltype(cj) y = x; // y的类型被推导为 const int &,y为指向常量的引用
decltype(cj) z; // 错误;引用类型必须初始化
decltype
括号中不是一个变量而是一个表达式时,此时decltype
推导出的的类型为表达式的类型:
int i = 42, *p = &i, &r = i;
decltype(r+0) b; // 正确;加法的结果时int,因此b是一个int
decltype(*p) c; // 错误;c是int&,必须初始化
r是一个int型引用,其值与i绑定,故decltype®
的结果为引用类型。r+0
表达式的运算结果是一int类型的具体值,故decltype(c+0)
推导出为int类型。
如果表达式的内容为解引用操作,则decltype
将得到引用类型。解引用指针得到指针所指的对象,故decltype(*p)
类型是int&
。
对于decltype
所用的表达式,如果变量名加上了括号,则得到的类型与不加括号时会有不同。如果使用的是不加括号的变量,则得到的结果是该变量的类型;如果加上了括号,编译器会将其当成表达式,得到引用类型。
decltype((variable))
(双括号)的结果永远是引用。而decltype(variable)
结果只有当variable本身是引用时才是引用。