auto 和 decltype 都是类型推断的方式
区别如下:
1、auto 是通过编译器计算变量的初始值来推断类型,decltype同样也是通过编译器来分析表达式进而得到它的类型,但是它不用将表达式的值计算出来
2、编译器推断出来的auto类型可能与初始值类型不同,众多周知,使用引用实际是使用引用的对象,特别是当引用被用作初始值时,真正参与初始化的值其实是引用对象的值,此时编译器以引用对象的类型作为auto的类型,比如对于顶层const,auto会忽略顶层const性质,但是decltype是保留下来的
int i = 0; &r = i; auto a = r //a是一个整数,r是i的别名,而i是一个整数
const int ci = i, &cr = ci; auto b = ci; //b是一个整数(ci的顶层const特性被忽略了) auto c = cr; //c是一个整数(cr是ci的别名,ci本身是一个顶层cosnt) auto d = &i; //d是一个整型指针(整数的地址就是指向整数的指针) auto e = &ci; //e是一个指向常量整型的指针(对常量对象取地址是一种底层cosnt) //如果希望推断出的auto类型是一个顶层const,需明确指出 const auto f = ci; //ci的推断类型为int,f是const int //还可以将引用的类型设为auto auto &g = ci; //g是一个整型常量引用,绑定到ci auto &h = 42; //错误:不能为非常量引用绑定字面值 cosnt auto &j = 42; //正确:可以将常量引用绑定字面值 //设置一个auto的引用时,初始值中的顶层常量仍然保留,如果要给初始值绑定一个引用,则此时的常量就不是顶层常量了。
3、与auto不同,decltype的结果类型与表达式形式有密切关系,比如declytpe内层没有括号得到的就是变量的类型,如果有多层括号,那么返回的就是引用,具体可通过代码分析
cosnt int ci = 0, &cj = ci; decltype(ci) x = 0; //x的类型是const int deceltype(cj) y = x; //y的类型是const int&,y绑定到变量x decltype(cj) z; //错误,z是一个引用,必须初始化
//引用从来都作为其所指对象的同义词出现,只有在decltype处是一个例外 //decltype和引用 //如果decltype使用的表达式不是一个变量,则decltype返回表达式结果对应的类型,decltype的返回值类型可以是引用类型 int i =42,*p = &i, &r = i; decltype(r + 0) b; //加法的结果时int,因此b是一个未初始化的int decltype(*p) c; //错误做法:c是int& 必须初始化 //如果表达式的内容是解引用操作,则decltype将得到引用类型,解引用指针可以得到指针所指的对象,而且还能给这个对象赋值,因此decltype(*p)的结果类型就是int&,而非int