类型别名
类型别名是一个名字,它是某种类型的同义词。
定义类型别名可以使用关键字typedef
typedef double wages; // wages是double的同义词 typedef wages base, *p; // base是double的同义词,p是double*的同义词
定义类型别名也可以使用别名声明
using SI = Sales_item; // SI是Sales_item的同义词
指针、常量和类型别名
typedef char *pstring; const pstring cstr = 0; // cstr是指向char的常量指针 const pstring *ps; // ps是一个指针,它的对象是指向char的常量指针。
声明语句中用到pstring时,其基本数据类型是指针,此时const pstring表示常量指针。
auto类型说明符
用它就能让编译器替我们取分析表达式所属的类型。是通过初始值来推算变量的类型,则要求auto必须有初始值
如果使用auto在一条语句中声明多个变量,则该语句中所有变量的初始基本类型都必须一样
auto i = 0, *p = &i; // 正确 auto sz = 0, pi = 3.14; // 错误
使用引用其实是使用引用的对象,特别是当引用被用作初始值时,真正参与初始化的其实是引用对象的值
auto一般会忽略顶层const,同时底层const则会保留下来。
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 ~ const int* // e是一个指向整数常量的指针(对常量对象取地址是一种底层const)
如果希望auto类型是一个顶层const,则
const auto f = ci; // ci ~ int, f ~ const int
&和*属于声明符,而非基本数据类型。在使用auto时需要特别注意。
int i = 0; const int ci = i, &cr = ci; auto k = ci, &l = i; // k ~ int // l ~ int& auto &m = ci, *p = &ci; // m ~ const int& // p ~ const int* // i ~ int // &ci ~ const int.
// 练习2.35:判断下列定义推断出的类型是什么。 const int i = 42; auto j = i; // j ~ int const auto &k = i; // &k ~ const int& auto *p = &i; // *p ~ int* const auto j2 = i, &k2 = i; // j2 ~ const int // &k2 ~ const int&
decltype
它的作用是选择并返回操作数的数据类型。编译器分析表达式并得到他的类型,却不实际计算表达式
decltype(f()) sum = x; // sum的类型是函数f的返回类型
decltype处理顶层const和引用与auto不同。
decltype使用的表达式是一个变量,则返回该变量的类型(包括顶层const和引用在内)
const int ci = 0, &cj = ci; decltype(ci) x = 0; // x ~ const int decltype(cj) y = x; // y ~ const int & decltype(cj) z; // 错误,z为引用,必须初始化
decltype的结果可以是引用类型
int i = 42, *p = &i, &r = i; decltype(r + 0) b; // decltype(r) 的结果是引用类型, // decltype(r + 0)的结果是int类型 decltype(*p) c; // 错误,c是int&,必须初始化
如果表达式的内容是解引用操作,则decltype将得到引用类型。
decltype结果与表达式形式密切相关。
如果decltype的表达式是一个变量,不加括号结果是该变量的类型,加上括号编译器会把它当初表达式。
变量是一种可以作为赋值语句左值的特殊表达式,所以这样的decltype会得到引用类型
decltype((i)) d; // 错误,d必须初始化,因为d ~ int& decltype(i) e; // 正确,e是一个未初始化的int
decltype((var))永远是一个引用
decltype(var)只有当var是一个引用时才是引用
decltype与auto区别
1、如果使用引用类型,auto会识别为其所指对象的类型,decltype会识别为引用的类型
2、decltype(())双括号的差别,双括号永远是引用
预处理器
确保头文件多次包含仍能安全工作的常用技术是预处理器
当预处理器看到#include标记时会用指定的头文件的内容代替#include
头文件保护符
头文件保护符依赖于预处理变量,预处理办理有两种状态:已定义和未定义。
#define指令把一个名字设定为预处理变量,另外两个指令则分别检查某个指定的预处理变量是否已经定义:
#ifdef当且仅当变量已定义时为真。
#ifndef当且仅当变量未定义时为真,
一旦检查结果为真,则执行后续操作直到遇到#endif指令为止
Tips:
1、使用typedef定义类型别名
2、使用using定义类型别名
3、当我们不知道变量表达式的类型时,可以使用auto让编译器为我们决定表达式的类型
4、auto会自动忽略掉顶层const,而底层const会被保留。
5、auto定义的变量必须有初始值。
6、decltype:希望从表达式的类型推断出想要定义的变量的类型,该操作返回操作数的类型。
7、赋值是会产生引用的一类典型表达式,引用的类型就是左值的类型,也就是说,如果i是int,则表达式i=x的类型是int&