2.5 处理类型
2.5.1 类型别名 (type alias)
类型别名是一个名字,它是某种类型的同义词,有两种方法可用于定义类型别名:
-
使用关键字
typedef
typedef double wages; // wages 是 double 的别名 typedef wages base, *p; // base 是 double 的同义词,p 是 double * 的同义词
关键字
typedef
作为声明语句中的基本数据类型的一部分出现。含有typedef
的声明语句定义的不再是变量而是类型别名。 -
使用别名声明(alias declaration),关键字
using
using SI = Sales_item; // SI 是 Sales_item 的同义词
用关键字
using
作为别名声明的开始,其后紧跟别名和等号,其作用是把等号左侧的别名规定成等号右侧类型的别名
指针、常量和类型别名
typedef char *pstring; // psting 等价于 char*
const pstring cstr = 0; // cstr 是一个常量指针
const pstring *ps; // ps 是指针,它指向的是一个 char 型的常量指针
注意,上述代码中声明语句的基本数据类型都是const pstring
,const
是对给定类型的修饰,因此const pstring
就是指向char
的常量指针,而非指向常量字符的指针。
遇到了一条使用了类型别名的声明语句时,人们往往会错误地尝试把类型别名替换成它本来的样子,以理解该语句的含义如
const pstring cstr = 0;
const char *cstr = 0; // 是对 const psting cstr 的错误理解
这种理解是错误的。声明语句中用到pstring
时,其基本数据类型是指针,可是用char*
重写声明语句后,数据类型就变成了char
,*
成为了声明符的一部分。前后两种声明的含义截然不同,前者声明了一个指向char
的常量指针,改写后的形式声明成了一个指向const char
的指针。
![](/qrcode.jpg)
2.5.2 auto 类型说明符
auto
让编译器通过初始值来推算变量的类型,采用auto
定义的变量必须有初始值。
使用auto
也能在一条语句中声明多个变量。因为一条声明语句只能有一个基本数据类型,所以该语句中所有变量的初始基本数据类型都必须一样。
复合类型、常量和 auto
编译器推断出的auto
类型有时候和初始值的类型并不完全一致,编译器会适当地改变结果类型使其更复合初始化规则。
-
使用引用时,编译器以引用对象的类型作为
auto
的类型 -
auto
一般会忽略掉顶层 const,同时底层 const 会保留下来,如果希望推断出的auto
类型是一个顶层 const,需要明确指出int i = 0; const int ci = i, &cr = ci; auto b = ci; // b 的类型是 int auto c = cr; // c 的类型是 int auto d = &i; // d 的类型是 int * auto e = &ci; // e 的类型是 int * const auto f = &ci; // f 的类型是 const int *
-
设置一个类型为
auto
的引用时,初始值中的顶层 const 属性仍然保留。如果我们给初始值绑定一个引用,则此时的常量就不是顶层 const 了
切记:符号&
和*
只从属于某个声明符,而非基本数据类型的一部分,因此初始值必须是同一种类型。
decltype 类型指示符
decltype
的作用是选择并返回操作数的类型说明,在此过程中,编译器分析表达式并得到它的类型,却不实际计算表达式的值
decltype(f()) sum = x; // sum 的类型就是函数 f() 的返回类型
decltype
和auto
处理顶层 const 和引用的方式有些许不同。如果decltype
使用的表达式是一个变量,则decltype
返回该变量的类型(包括顶层 const 和引用在内)
const int ci = 0, &j = ci;
decltype(ci) x = 0; // x 的类型是 const int
decltype(cj) j = x; // j 的类型是 const int&
decltype(cj) z; // 错误, z 的类型是 const int&,必须要有初始值
decltype 和引用
如果decltype
使用的表达式不是一个变量,则decltype
返回表达式结果对应的类型。当表达式返回的一个引用类型时,意味着可以该表达式的结果对象能作为一条赋值语句的左值
int i = 42, *p = &i, &r = i;
decltype(r + 0) b; // 正确:加法的结果是 int,所以 b 的类型是 int
decltype(*p) c; // 错误:解引用的结果是 &,所以 c 的类型是 int&,必须初始化
对于decltype
所用的表达式来说,如果变量名加上了一对括号,则得到的类型与不加括号时会有不同。
- 如果
decltype
使用的是一个不加括号的变量,则得到的结果就是该变量的类型; - 如果给变量名加上了括号,得到的结果是引用类型
decltype((i)) d; // 错误:d 的类型是 int&,必须初始化
decltype(i) e; // 正确:
切记:decltype((variable))
的结果永远是引用,decltype(variable)
的结果仅当variable
的类型是引用才是引用。