复合类型(compound type)是指基于其他类型定义的类型。C++语言有几种复合类型。
本章介绍:引用和指针
普通声明:
基本数据类型(base type) + 声明符(declarator)
2.3.1 引用
Note: 严格来说使用术语“引用(reference)”时,指的是“左值引用(lvalue reference)”
引用为对象起了另外一个名字,引用类型引用另外一种类型。
通过将声明符写成&d的形式来定义引用类型,其中d是声明的变量名
int ival = 1024;
int &refVal = ival; //refVal 指向ival (是ival的另一个名字)
int &refVal2; //报错:引用必须被初始化
一般初始化变量时,初始值会被拷贝到新建的对象中。定义引用时,程序把引用和它的初始值绑定(bind)在一起,无法令引用重新绑定到另外一个对象,引用必须初始化。
引用即别命名
Note:引用并非对象,相反的,它只是为一个已存在的对象所起的另外一个名字。
定义了一个引用后,对其进行的所有操作都是在与之绑定的对象上进行的
为引用赋值实际上是赋值给了与引用绑定的对象
引用本身不是一个对象
不可定义引用的引用
引用的定义
引用类型初始值一定是个对象
引用类型的初始值和引用类型一致
2.3.2 指针(重要!!!)
指针(pointer)是指向另一种类型的复合类型。
与引用类似,指针也实现了对其他对象的间接访问。
与引用不同,
其一,指针本身就是一个对象,允许对指针复制和拷贝,指针生命周期内它可以先后指向几个不同的对象。
其二,指针无需在定义时赋初始值。和其他内置类型一样,在块作用域内定义的指针如果没有被初始化,也将拥有一个不确定值。
定义指针类型的方法将声明符写成*d的形式
获取对象的地址
指针存放某个对象的地址,要想获取该地址,需要使用 取地址符(操作符&)
int *p = &ival
//p存放变量ival的地址,或者说p是指向变量ival的指针
除p56和p534要介绍的两种例外情况,其他的所有指针的类型都要和它所指向的对象严格匹配。
double dval;
double *pd = &dval; // 正确:初始值是double类型对象的地址
double *pd2 = pd; //正确:初始值是指向double对象的指针
int *pi = pd; //错误: 指针pi的类型和pd的类型不匹配
pi = &dval //错误:试图把double型对象的地址赋给int型指针
指针值
指针的值(即地址)应该属于下列4种状态之一;
1.指向一个对象
2.指向紧邻对象所占空间的下一个位置
3.空指针,意味着指针没有指向任何对象
4.无效指针,也就是上述情况外的其他值
试图拷贝或以其他方法访问无效指针的值都将引发错误
2,3情况的指针有效但是不允许访问
利用指针访问对象
如果指针指向了一个对象,则允许使用 解引用符(操作符*)来访问该对象
int ival =42;
int *p = &ival; //p存放着变量ival的地址,或者说p是指向变量ival的指针
cout << *p //由符号8得到的指针p所指的对象,输出为42
Note: 解引用操作仅适用于那些确实指向了某个对象的有效指针
关键概念:某些符号有多重含义
int i = 42;
int &r = i; &紧随类型名出现,因此是声明的一部分,r是一个引用
int *p; *紧随变量名出现,因此是声明的一部分,p是一个指针
p = &i; &出现在表达式中,是一个取地址符
*p = i; *出现在表达式中,是一个解引用符
int &r2 = *p &是声明的一部分,*是一个解引用符
空指针
空指针(null pointer)不指向任何对象
生成空指针方法:
- int *p1 = nullptr;
- int *p2 = 0 ;
- int *p3 =NULL; //需要#include cstdlib ,定义在cstdlib中的名为NULL的预处理变量
建议:初始化所有指针
赋值和指针
赋值改变的是等号左侧的对象
pi = &ival; //pi的值被改变,现在pi指向了ival
*pi =0; //ival的值被改变,指针pi没有发生改变
其他指针操作
指针拥有合法的值
指针的值是0则返回false,其他情况返回true
可以用操作符(== !=)比较两个指针,如果指针存放地址相同,则它们相等。
相等有三种情况:
都为空
都指向同一个对象
都指向同一个对象的下一地址
一个指针指向某对象,另一个指针只想另外对象的下一地址可有可能
void*指针
void*是特殊的指针类型,可以用于存放任意对象的地址,任意类型指针
不能操作void*指针所指的对象,因为不知道这个对象是什么类型
2.3.3 理解复合类型的声明
定义多个变量
略
指向指针的指针
指针式内存中的对象,像其他对象一样也有自己的地址,因此允许把指针的地址再存放到另一个指针中。
通过*的个数可以区分指针的级别,**是指向指针的指针
int ival = 1024;
int *pi =&ival; //pi指向一个int型的数
int **ppi = π //ppi指向一个int型的指针
指向指针的引用
引用本身不是一个对象,因此不能定义指向引用的指针,但能指向指针的引用
int I =42;
int *p; //p是一个int型指针
int *&r =p; //r是对指针p的引用
r =&I; //r引用了一个指针,因此给r赋值就是令p指向I
*r =0 //将i的值改为0
TIPS: 面对一条比较复杂的指针或引用的声明语句时,从 右向左读