20170911_decltype和auto的区别
顶层const 和 底层const:
指针本身是一个对象,它又可以指向另外一个对象,因此,指针本身是不是常量、以及指针所指的对象是不是一个常量 就是两个相互独立的问题。
1、用 顶层const 来描述 指针本身是一个常量,即指针常量。
2、用 底层const 来描述 指针所指的对象是一个常量,即常量指针。
(这两个概念,就是指针常量和常量指针的区别。
参考博客: 20170911_指针常量和常量指针的区别以及const和define的区别 )
decltype 类型说明符 的说明:
1、问题引出:
有时会遇到这种情况,需要从表达式的类型来推断出要定义的变量的类型,但是不想用该表达式的值来初始化该变量。
为了满足这种需求,C++11 新标准引入了 decltype 类型说明符,在此次过程中,编译器会分析表达式并且得到表达式的类型,却不实际计算表达式的值。
比如:decltype(fun( )) sum =x; sum 的类型是函数fun() 的返回值类型。
解释:编译器并不实际调用该函数fun(),而是使用 假设当调用函数fun() 的时候,它的返回值类型就作为 sum 的类型。
2、decltype 处理顶层const 和底层const 的时候:
const int ci = 0, &cj = ci; ci 是一个常量变量,cj 是一个常量变量的引用。
decltype( ci ) x = 0; x 的类型:const int 类型
decltype( cj ) y = x; y 的类型:const int & 类型,并且绑定到变量x 上。
decltype( cj ) z; z 的类型 const int & 类型,因此它必须初始化,但是 z 没有初始化,所有出错!
解释:cj 是一个引用,decltype( cj ) 的结果就是引用类型,因此作为引用类型的z 必须被初始化。
3、decltype 和引用:
如果 decltype 使用的表达式不是一个变量,则 decltype 返回的是表达式对应的类型。
decltype 的结果可以是引用类型。
int i =42, *p=&i, &r=i;
decltype( r+0 ) b; 正确。
decltype( *p ) c; 错误。
解释1: r 是一个引用,因此 decltype( r ) 的结果是一个引用类型,必须得被初始化。如果想让decltype 的返回类型是 r 所指向的类型,可以把 r 作为表达式的一部分,如 r+0,显然这个表达式 decltype( r+0 ) 的结果类型是 int 型而不是一个int 引用类型。
解释2: 如果表达式的内容是一个解引用操作 如 *p,则decltype 的返回值类型是引用类型。正如我们熟悉的那样,解引用指针可以得到指针所指的对象,而且还可以给这个对象赋值。因此,decltype( *p ) 的结果是 int & 类型,而不是int 类型!
4、decltype 和 auto 的一个重要区别:
对于decltype 所用的表达式来说,如果变量名加上了一对括号(),则得到的类型与不加括号时不一样。
如果decltype 使用的是一个不加括号的变量,则得到的结果就是该变量的类型。
如果decltype 使用的是一个加了一层或者多层括号的变量,则编译器会把它当成是一个表达式。变量是一种可以被赋值的左值表达式,因此 这样的 decltype 就会得到 引用类型。
int i = 42, j = 50;
decltype(( i )) d; decltype 的表达式是加了括号的变量,所以得到的是引用,必须得被初始化。因此,这句话出错!!!
decltype(( i )) d2 = &j; decltype 的表达式是加了括号的变量,所以得到的是引用,必须得被初始化。正确。
decltype( i ) d3; decltype 的表达式是没有加括号的变量,所以得到的是该变量的类型,所以 d3 是一个未被初始化的变量。
auto 类型说明符的说明:
1、C++11新标准引入了auto 类型说明符,用它就能让编译器替我们去分析表达式所属的类型,auto 是编译器通过初始值来推断变量的类型的。显然,使用auto定义变量 时,必须要有初始值!
使用auto 也能在一条语句中声明多个变量,但是这些变量一定要是同类型的,否则出错!
auto i = 0, j=1.1; i 和 j 不是同类型,出错。
auto i = 0, *p = &i; i 是整型,p 是整型指针,正确。
2、使用引用,其实使用的是引用的对象,特别是当引用被用作初始值的时候,真正参与初始化的其实是引用对象的值,因此,编译器是使用引用对象的类型来作为auto 的类型。
int i = 0, &r = i;
auto a = r; 正确,a 的类型是r 做引用的变量的类型,即 int 类型。
另外,auto 会去除掉顶层const 属性,同时,底层const 属性会保留下来。
const int ci = i, &cr = ci;
auto b = ci; b 是一个整数,ci 的顶层const 属性被忽略掉。
auto c = cr; c 是一个整数,cr 是 ci 的别名,ci 本身是一个顶层 const。
auto d = &i; d 是一个整型指针,整数的地址就是指向整数的指针。
auto e = &ci; e 是一个指向整数常量的指针。