1. 类型别名:
定义类型别名的方式有两种:
传统方法使用typedef关键字
typedef int aaa; //aaa是int 的同义词;
typedef aaa bbb, *p; //bbb是int的同义词,p是int* 的同义词;
C++11新标准:使用别名声明来定义类型的别名
using m_int = int; //使用m_int 作为int的别名;
m_int b = 50;
cout << typeid(b).name() << endl; //输出为 int
重点注意一下任意混淆的点:指针、常量和类型别名
typedef char *pstring;
const pstring cstr = 0;
const pstring *ps;
通常会出现一种错误的理解,即直接把类型别名替换为它本来的样子,理解为:
const char *cstr = 0; //错误理解
声明语句中用到pstring时,基本类型是指针。可这样的错误理解的情况下,*成为了一个声明符,数据类型变成了char,两种方式含义完全不同;
这样会将cstr理解为一个指向常量字符的指针,而实际上,pstring表示为指向char的指针,增加const关键字修饰后应该表示为一个 常量指针
而ps是一个指针,对象是指向char的常量指针
2. auto类型说明符
C++11引入了auto类型说明符,能让编译器去分析所属类型
auto变量必须有初始值:
auto val3 = val1 + val2; //根据val1和val2 推算出val3的数据类型
复合类型、常量和auto
auto和引用:引用作为auto类型的初始化值时,编译器会将auto初始化为引用的对象的类型:
int i = 1;
int &r = i;
auto a = r; //a是一个整数
auto一般会忽略掉顶层const,底层const会被保留:
const int val = 10;
auto b = val; //b是一个整数(val的顶层const被忽略)
auto c = &val; //c是一个指向整数常量的指针 (对常量对象取地址是底层const)
如果希望推断出顶层const,需要明确指出:
const auto d = val;
设置一个类型为auto的引用时,初始值中的顶层常量属性仍然保留;如果给初始值绑定一个引用,此时常量就不是顶层常量了
const int ci = 10;
auto &val = ci; //val 表示一个整型常量引用,绑定到ci
auto &a = 43; //错误,不能为非常量引用绑定字面值
const auto &b = 43; //正确
3. decltype类型指示符
C++引入第二种类型说明符,选择并返回操作数的数据类型
decltype(f()) sum = x; //sum的类型就是函数f的返回类型
编译器并不实际调用函数f;
decltype处理顶层和auto不同。如果decltype括号里是一个变量,则返回该变量的类型(包括顶层const和引用在内)
const int ci = 0, &cj = ci;
decltype(ci) x = 0; //x类型为const int
decltype(cj) y = x; //y类型为const int&, y绑定到变量x
注意:引用从来都是作为所指对象的同义词出现,只有deltype例外
decltype和引用
int i = 0, *p = &i;
decltype(r + 0) b //加法结果是int
decltype(*p) c; //c是int&, 必须初始化,如果表达式的内容是解引用操作,则返回的是引用类型
切记:decltype( (variable) ) (双层括号)的结果永远是引用,而decltype(variable)结果只有当variable本身是引用时候才引用;
赋值是会产生引用的一类型表达式,即:
decltype (a = b) d = a;
此时d表示为a的引用,同时表达式a == b不会被执行;