复合类型是指基于其他类型定义的类型;一条声明语句由一个基本数据类型和紧随其后的一个声明符列表组成
2.3.1 引用
【使用格式:
int i = 0;
int &a = i;//a 为对整形对象i 的引用
】
【引用为对象起了另外一个名字,引用类型引用另外一种类型。
引用并非对象,它只是为一个已经存在的对象所起的另外一个名字,所以不能定义引用的引用。】
【定义引用时,程序把引用和它的初始值绑定在一起,而不是将初始值拷贝给引用。
一旦初始化完成,引用将和它的初始值对象一直绑定在一起。
因为无法令引用重新绑定至另一个对象,因此引用必须初始化。】
【定义了一个引用之后,对其进行的所有操作都是在与之绑定的对象上进行的。
所以大多情况下,引用的类型必须和与之绑定的类型严格匹配(否则由于不同类型能进行的操作不同,对引用进行的操作可能无法应用于其绑定的对象)。
大多情况下,引用只能绑定在对象上,而不能与字面值或某个表达式的计算结果绑定在一起。】
【使用引用而非直接传递参数,可以提高函数的空间性能和时间性能。
引用因为不创建新的对象,在函数中传递参数时要比直接传递的性能好很多,尤其是传递使用者定义的复杂类的时候。】
2.3.2 指针
【引用与指针的异同:
第一, 指针和引用都实现了对其他对象的间接访问;
第二,指针本身就是一个对象,允许对指针赋值和拷贝,而且在指针的生命周期内它可以先后指向几个不同的对象;
第三,指针无须在定义时初始化,而引用必须在定义时初始化。】
【一条定义语句可以定义出不同类型的变量,但都是基于声明语句开始的基本类型的类型。
定义指针的* 只作用于其后紧跟的一个变量名(实际上int* b 也能定义指针b,但容易产生误解)。
int a,*b = &a,c;
//上条语句中定义了整形变量a 和c,以及指向整形a 的指针变量b
】
【在声明语句中指针的类型必须要与其所指向对象的类型所匹配。】
【引用和指针中涉及到的符号的用法及不同意义:
int i = 42;
int &r = i;//& 紧跟类型名,是声明符列表的一部分,r 是一个引用
int *p = &i;//* 出现在类型名后的声明符列表中,p 是一个指针;& 出现在表达式中,是一个取地址符
*p = 43;//* 出现在表达式中,是一个解引用符
】
【指针的字面值:nullptr(空指针):
int *p = nullptr;//等价于*p = 0;
int *p = 0;
int *p = NULL;//在头文件cstdlib 中定义,在新标准下尽量避免使用NULL
】
【把int 直接赋值给指针是错误的操作,即使int 变量的值恰好等于0 也不行。
因为对于程序员,使用指针时相当于使用了基址寻址的方法,而在不知道基址的值时对指针赋具体的值毫无意义。】
【将合法指针(有效指针)用于条件表达式时:
只当指针为空指针时,条件才为false。】
【void* 指针是一种特殊的指针类型,可用于存放任意对象的地址。
但不能直接操作void* 指针所指的对象,因为我们不知道该指针所指对象的类型,更不知道该类型可以进行哪些合法的操作。】
2.3.3 理解复合类型的声明
【存在指向指针的指针,对指针的引用。
int i = 0;
int *p = &i;//p 是指向整形i 的指针
int **q = &p;//q 是指向指针p 的指针
int *&r = p;//r 是对指针p 的引用
int **&t = q;//t 是对指针q 的引用
不存在引用的引用,也不存在指向引用的指针(引用本身不是对象)。】