auto的作用是自动类型推导
顶层const与底层const
- 顶层const:修饰左值全部数据类型
- 底层const:修饰左值部分数据类型
const int i = 0; //顶层const, 左值全部数据类型为int, 修饰的也是int const int* p1 = &i; //底层const, 左值全部数据类型为int*, 修饰的是int int a = 0; int* const p2 = &a; //顶层const, 左值全部数据类型为int*, 修饰的是int* const int& s = a; //底层const, 左值全部数据类型为int&, 修饰的是int
数组和函数类型的退化
void func(int, int); //func的类型为 void (int, int) int main(void) { int array[] = { 1, 2, 3 }; //array的类型为int [3]; int* p = array; //int [3] 类型赋值给了 int* 类型 void* p2 = func;//void (int, int) 类型赋值给了 void* } void func(int, int) { }
能赋值成功的秘密就是编译器进行了处理,将数组和函数的首地址拿了出来,也就是退化了。现在,我用auto关键字来进行证明。
int array[] = { 1, 2, 3 }; auto p1 = array;//p1的类型为int*,因为array退化了 auto& p2 = array;//我们惊奇的发现:p2的类型为int(&)[30]。 void func(int, double) {} auto p1 = func;//p1的类型为void(*)(int, double),因为func退化了 auto& p2 = func;//p2的类型为void(&)(int, double)。这符合我们的预期 (*p1)(1, 2.0);//这很指针 p2(1, 2.0);//这相当于就是func()
ParamType param = expr e;//ParamType:auto*,auto&,const auto 等等之类的组合 //param左值变量名 //expr:右值类型
现在我来说明auto类型推导的规则
1)当ParamType既不是指针也不是引用时(即不是:auto*,auto&)
- 如果expr是引用,那么引用除去(如:int& => int)
- 在上一步之后,如果此时expr有顶层const,那么将其除去
- 在上一步之后,取expr和ParamType(除去auto)的并集,就是PramType的类型,去除PramType原有的组合部分,就是auto的类型
int i = 0; const int ci = 0; int* pi = &i; const int* cpi = &ci; int* const pic = &i; int& ii = i; const int& cii = i; auto p = i; //int auto p2 = ci; //int,因为ci有顶层const auto p3 = pi; //int* auto p4 = cpi; //const int*, 因为是cpi底层const,不用去除 auto p5 = pic; //int*, 因为是pic顶层const auto p6 = ii; //int, 因为ii有引用 auto p7 = cii; //int, 因为cii去除引用后,const int为顶层const
2)当ParamType是指针时
步骤同1)一样
int i = 0; const int ci = 0; int* pi = &i; const int* cpi = &ci; int* const pic = &i; int& ii = i; const int& cii = i; auto* p = &i; //int* auto* p2 = &ci; //const int*,因为&ci相当于const int*,是底层const auto* p3 = pi; //int* auto* p4 = cpi; //const int*, 因为是cpi底层const,不用去除 auto* p5 = pic; //int*, 因为是pic顶层const auto* p6 = ⅈ //int*, 因为&ii有引用 auto* p7 = &cii;//const int*, 因为&cii去除引用后,const int*为低层const
3)当ParamType是引用时
- 如果expr是引用,那么引用除去(如:int& => int)
- 在上一步之后,取expr和ParamType(除去auto)的并集,就是PramType的类型,去除PramType原有的组合部分,就是auto的类型
int i = 0; const int ci = 0; int* pi = &i; const int* cpi = &ci; int* const pic = &i; int& ii = i; const int& cii = i; auto& p = i; //int& auto& p2 = ci; //const int& auto& p3 = pi; //int* & auto& p4 = cpi;//const int* & auto& p5 = pic;//int* const & auto& p6 = ii; //int& auto& p7 = cii;//const int&
4)当ParamType为通用引用时(auto&&)
- 当右值为一个变量名时,去掉一个&,按auto&的规则推导
- 当右值是文字量(如:0,1等),按1)的规则推导
以上的推导规则也适用于模板的类型推导
另外,auto对于{},函数返回值和Lamda表达式的推导有缺陷。