在秋招笔试中遇到这样一道题目,于是编写该文章对decltype进行一个总结,方便以后翻阅。
C++有两种类型说明符,auto和decltype。它们的区分在于auto必须要计算表达式然后推断数据类型,而decltype不实际计算表达式的值。
1.以函数作为参数
int f(){
int i = 1;
cout<<i<<endl;
return i;
}
decltype(f()) sum = 1;
当我们执行上述代码,不会输出i的值,因为f函数并不会真的执行。decltype为sum指定的类型,就是假设f被调用将会返回的类型,也就是int类型。
2.以变量作为参数
const int ci = 0, &cj = ci;
decltype(ci) x = 0; //x的类型是const int
decltype(cj) y = x; //y的类型是const int&,y绑定到变量x
decltype(cj) z; //错误,z是一个引用,必须初始化
如果decltype的参数是变量,则decltype返回该变量的类型(包括顶层const和引用在内)。特别,引用一般都作为其所指对象的同义词出现,只有用在decltype处是一个例外。
另外,对于decltype来说,如果变量名加上括号,就会得到引用类型。
int i = 123;
decltype(i) a; //正确,a是int类型
decltype((i)) b; //错误,b是int&,必须初始化
因此,题目中的A选项是错误的。
切记:decltype((var))(注意是双层括号)的结果永远是引用,而decltype(var)结果只有当var本身就是一个引用时才是引用。
3.以解引用作为参数
int i = 123, *p = &i;
decltype(*p) c = i; //正确
decltype(*p) c; //错误,c是int&,必须初始化
如果参数是解引用类型,则decltype将得到引用类型。解引用指针可以得到指针所指的对象,而且还能给这个对象赋值。所以上述decltype得到的是int&,而不是int。
这就是C选项错误的原因,引用必须要初始化。
3.以表达式作为参数
int i = 123, *p = &i, &r = i;
decltype(r + 0) x; //正确,加法的结果是int
decltype(*p + r) x; //正确。加法的结果是int
如果参数是r,得到的结果是引用类型。如果参数是r + 0,此时r处于表达式当中,相当于i的别名,该表达式就是i + 0,得到的类型就是int。所以D选项是正确的。
如果参数是表达式,*p就是指代i的值,r也是指代i的值,加在一起是int。