类型别名
类型别名是一个名字,它是某种类型的同义词。使用类型别名有很多好处,它让复杂的类型名字变得简单明了、易于理解和使用,还有助于程序员清楚地知道使用该类型的真实目的。
有两种方法可用于定义类型别名:
1. typedef
typedef double wages; // wages是double的同义词
typedef wages base,*p; // base是double的同义词,p是double*的同义词2222
2. using
新标准规定了一种新的方法,使用别名声明来定义类型的别名:
using SI = Sales_item; // SI是Sale_item的同义词
using ii = int; // ii是int的同义词
如果某个类型别名指代的是复合类型或常量,那么把它用到声明语句里就会产生意想不到的后果。例如下面的声明语句用到了类型pstring,它实际上是类型char*的别名:
typedef char *pstring; // using pstring = char *;
const pstring cstr = 0; // cstr是指向char的常量指针
const pstring *ps; // ps是一个指针,它的对象是指向char的常量指针
上述两条声明语句的基本数据类型都是const pstring,和过去一样,const是对给定类型的修饰。pstring实际上是指向char的指针。因此,const pstring就是指向char的常量指针,而非指向常量字符的指针。即:
typedef int *pstring;
int a = 5,b = 10;
cout << "addr(a) = " << &a << endl;
const int *p = &a; // p指向的对象为常量
const pstring q = &a; // q指针为常量
cout << "p = " << p << endl;
cout << "q = " << q << endl;
p = &b;
// q = &b; // wrong
cout << "p = " << p << endl;
auto类型说明符
C++11新标准引入了auto类型说明符,用它就能让编译器替我们去分析表达式所属的类型。和原来那些只对应一种特定类型的说明符(比如double)不同,auto让编译器通过初始值来推算变量的类型。显然,auto定义的变量必须有初始值:
// 由val1和val2相加的结果可以推断出item的类型
auto item = val1 + val2; // item初始化为val1和val2相加的结果
auto能在一条语句中声明多个变量,但是其变量只能有一个基本数据类型:
auto i = 0,*p = &i; // 正确,i是整数、p是整形指针
auto sz = 0,pi = 3.14 // 错误,sz和pi的类型不一致
auto一般会忽略掉顶层const,而底层const将保留下来:
const int ci = i,&cr = ci;
auto b = ci; // b是一个整数(自动忽略顶层const)
auto d = &ci; // d是一个指向整数常量的指针(对常量对象取地址是一种底层const)
decltype类型指示符
C++11新标准引入了第二种类型说明符decltype,它的作用是选择并返回操作数的数据类型。在此过程中,编译器分析表达式并得到它的类型,却不实际计算表达式的值:
decltype(f()) sum = x; // sum的类型就是函数f的返回类型
const int ci = 0,&cj = ci;
int i = 42,&r= i;
decltype(ci) x = 0; // x的类型就是const int
decltype(cj) y = x; // y的类型就是const int&,y绑定到变量x
decltype(r + 0) b; // 加法结果为int,因此b为int
decltype(cj) z; // 错误:z是一个引用,必须初始化
// decltype的表达式若加上了括号,结果将是引用
decltype(i) f; // 正确:f是一个(未初始化的)int
decltype((i)) g; // 错误:g是int&,必须初始化