数据类型

类型别名

程序越复杂,程序的类型也会越复杂。类型复杂体现在两点:

1、 难于拼写,且不能体现其真实目的和含义。

2、 程序员不了解程序的情况下,无法确定需要声明什么样的类型。

类型别名可使程序的类型名字变得简单明了、易于理解和使用。类型别名需要使用typedef关键字,如:

1 typedef double wages;  //wages和double是同义词。wages含义和目的比double更明确,也更易于程序员在不了解程序的情况下,确定什么样的变量需要声明为wages。 
2 typedef wage base , *p; //base是double的同义词,p是double*的同义词。

C++11新标准可使用using关键字声明类型别名,如:

1 using wages = double; //wages是double的同义词,等价于typedef double wages;  

类型别名和类型的名字等价,只要是类型的名字能出现的地方,就能使用类型别名。

 

另外,使用类型别名声明const的指针时,需要注意理解下面第三行代码:

1 int i = 0; 
2 using pint = int *; 
3 const pint ci = &i;  //ci是指向int的常量指针,而非指向常量int的指针。 

特别注意的是pint不能简单的替换成int *,理解成:

1 const int *ci = &i; //这里ci是指向常量int类型的指针,而非指向int的常量指针。

为了解释这种情况,我们可以这样理解:声明语句中用到的pint,其基本数据类型是指针。可是替换成int *重写声明语句后,数据类型变成了int,*成了声明符的一部分,这样的结果是:const int成了基本数据类型,指针ci指向const int;而当pint是基本数据类型时,基本类型就是一个指针,const pint表示指针是常量,所以ci就是常量指针,它指向int数据类型。

 

auto类型说明符

在把表达式的值赋给变量,就要求声明变量的时候清楚知道表达式的类型。然而要做到这一点并非那么容易,有时根本做不到。为了解决这个问题,C++11新标准引入了auto类型说明符。

1 auto item = val1 + val2; //由val1和val2相加的结果可以推断出item的类型  

auto能让编译器替我们去分析表达式所属的类型。通过初始值来推算变量的类型。显然,auto定义的变量必须有初始值。 使用auto也能在一条语句中声明多个变量:

1 auto i = 0, *p = &i;   //正确 
2 auto sz = 0, pi = 3.14; //错误:sz和pi的类型不一致。

需要注意的是auto一般会忽略掉顶层const(声明指向常量变量的常量指针时:const char * const pc = 0,第一个const是底层,第二个const是顶层),同时底层const会保留下来,如:

1 const int ci = i, &cr = ci; 
2 auto b = ci; //b是一个整数(ci的顶层const特性被忽略掉了) 
3 auto c = cr; //c是一个整数(cr是ci的别名,ci本身是一个顶层const) 
4 auto d = &i; //d是一个整形指针 
5 auto e = &ci;//e是一个指向整数常量的指针(对常量对象取地址是一种底层const)

如果希望推断出的auto类型是一个顶层const,需要明确指出:

1 const auto f = ci;

另外,还可以将引用类型设为auto:

1 auto &g = ci;  //g是一个整形常量的引用,绑定到ci。


decltype类型指示符

有时我们希望从表达式的类型来定义变量的类型,但是不想用该表达式的值初始化变量。可以使用decltype类型指示符。

1 decltype(f()) sum = x;  //sum的类型就是函数f的返回类型。 

编译器并不实际调用函数f,而是当调用发生时,使用f的返回值类型作为sum的类型。

 

decltype处理顶层const和引用的方式与auto有些许不同。如果decltype使用的表达式是一个变量,则decltype返回该变量的类型,包括顶层const和引用在内。如:

1 const int ci = 0, &cj= ci; 
2 decltype(ci) x = 0; //x的类型是const int。 
3 decltype(cj) y = x; //y的类型是const int &, y绑定到变量x。 
4 decltype(cj) z;  //错误:z是一个引用,必须初始化。

decltype和引用:

当decltype使用的表达式不是变量,则返回表达式结果对应的类型。而且有些表达式将向decltype返回一个引用类型:

1 int i = 42, *p = &I, &r = i; 
2 decltype(r + 0) b;   //正确:加法的结果是int,因此b是一个未初始化的int。 
3 decltype(*p) c; //错误:c是int &,必须初始化。

因为r是一个引用,因此decltype(r)的结果也是引用类型,而表达式r+0的结果显然是一个具体的值,而非一个引用。另一方面,如果表达式的内容是解引用操作,则decltype也将得到引用类型。因为解引用指针可以得到指针所指的对象,而且还能给这个对象赋值。因此,decltype(*p)的结果类型就是int &,而非int。

decltype和auto的另一处重要区别是,decltype的结果类型和表达式的形式密切相关。如:

1 decltype((i)) d; //错误:d是int &,必须初始化。 
2 decltype(i) e; //正确:e是一个(未初始化的)int。

上述代码中,如果i变量不加括号,得到的结果是该变量的类型。如果i变量加括号,编译器就会把它当成是一个表达式。变量是一种可以作为赋值语句左值的特殊表达式,所以这样的decltype就会得到引用类型。

 

posted @ 2016-01-05 09:27  收着心生活  阅读(347)  评论(0编辑  收藏  举报