Proletarier aller Länder vereinigt Euch

C++:关于复合类型

2017/11/27

复合类型有两种:引用和指针;
引用(reference)为对象起了一个新名字(不是新建对象),通过将声明符写成&d的形式来定义引用类型,d是声明的变量名。

1
2
int ra =100;
int &ref_ra = ra; //ref_ra引用到ra

在变量初始化时,新建对象的赋值是相当于拷贝(copy),而引用的赋值是绑定(bind),绑定无法同被绑对象解除,因此引用必须初始化;
以引用作为初始值,相当于以被引用对象的值作为初始值;
因为引用不是对象,所以不能定义引用的引用(但可以定义指针的指针)。

1
2
3
int ref_ra = 200; //等价于 ra = 200
int rb = ref_ra; //等价于 rb = ra
int &ref_ref_ra = ref_a; //错误,不能定义引用的引用

引用类型必须与被绑定对象严格匹配(除了const),并不能直接引用计算结果。

1
int &ref_rb = 200; //错误,无法直接引用计算结果

指针(pointer)也是一种实现对其他对象间接访问的复合数据类型。指针自身也是一个对象,所以指针可以直接赋值和拷贝。
指针实际上是一段内存地址,这个地址存放了指针所指对象的数据;获取对象的地址需要使用取址符&
指针是C/C++初学者的噩梦(*。>Д<)

1
2
int pa = 2333;
int *ptr_pa = &pa; //指针ptr_pa存放变量pa的地址,即ptr_pa指向pa

和引用相同,指针必须和被指向对象类型严格匹配(同样除去const这一情况)。

茴字有四种写法,指针也有四种状态:

1
2
3
4
1.指向一个对象
2.指向紧邻对象所占空间的下一位置
3.空指针,没有指向任何对象
4.无效指针,不属于上面三种情况的就是这种状态(真是废话)

虽然逻辑上这个分类有点扯淡,但是无效指针引发的bug是实打实的,因为编译器无法识别无效指针的bug,所以使用指针时要头脑清醒。

使用指针访问对象:
使用解引用符*来实现

1
2
int pb = 666;
int *ptr_pb = &pb; //等价于指针ptr_pb指向对象pb;ptr=pb的内存地址;*ptr_pb=pb

划重点了,虽然C++的符号表中并未写明,但*与&这两个符号在声明中和在表达式中有不同的意义:

1
2
3
4
int i = 99;
int &ref_i = i; //&用于声明
int *ptr_i = &i; //*用于声明,&用于取地址
int &ref_ptr_i = *ptr_i; //&用于声明,*用于解除引用

空指针(null pointer)是不指向任何对象的指针,定义空指针有三种方法:

1
2
3
int *ptr_k1 = nullptr; //C++11新标准中的新写法,推荐使用此种;nullptr是一种特殊类型的字面值,可以被转换成任意其他的指针类型
int *ptr_k2 = 0;
int *ptr_k3 = NULL; //NULL是C++中的预处理变量,在cstdlib.h中定义,NULL = 0;

注意,虽然定义空指针时的右值等价于0,但是不能将0的int形式赋给指针:

1
2
int *ptr_l;
ptr_l = 0; //错误,不能把int变量直接赋值给指针

又要划重点了,虽然指针未初始化不会引发语法错误,但是极容易造成程序崩溃,这种错误在debug时非常棘手;
因为未经初始化的指针所占内存空间的当前内容将被看做一个地址值,相当于要去访问一个不存在位置的不存在对象
(对象什么的,不存在的);比没对象更糟糕的是,指针所占的内存空间恰好能被当做内存地址,
就会造成合法性判断的混淆。所以,请务必初始化指针,不晓得指针指向何处的话就先将其初始化为nullptr吧(๑•̀ㅂ•́)و✧

CATALOG