0%

Cpp基础(2)引用与指针

引用与指针

复合类型(compound type)是指基于其他类型定义的类型,引用和指针是其中的两种。

一般地,一条声明语句由一个基本数据类型(base type)和紧随其后的一个声明符(declarator)列表组成。

引用

当我们使用“引用(reference)”时,指的其实是“左值引用(lvalue reference)”。

引用为对象起了另外一个名字,引用类型引用另外一种类型。通过将声明符写成$d的形式来定义引用类型。在定义引用时,程序把引用和它的初始值绑定(bind)在一起,而不是将初始值拷贝给引用。引用将和它的初始值对象一直绑定在一起,无法令其绑定到另外一个对象。

为引用赋值,实际上是把值赋给了与引用绑定的对象。获取引用的值,实际上是获取了与引用绑定的对象的值。以引用作为初始值,实际上是以引用绑定的对象作为初始值。

允许在一条语句中定义多个引用,其中每个引用标识符都必须以符号&开头。

引用的类型都要和与之绑定的对象严格匹配。引用只能绑定在对象上,而不能与字面值或某个表达式的计算结果绑定在一起。

1
2
3
4
5
6
7
8
9
10
int ival = 1024;
int &refVal = ival; //refVal指向ival
int &refVal2; //错误。引用必须被初始化

refVal = 2; //把值赋给了ival
int &refVal3 = refVal; //正确:refVal3绑定到了那个与refVal绑定的对象上,即ival
int i = refVal; //相当于i = ival

int i = 1024, i2 = 2048;
int &r1 = i, &r2 = i2;

指针

指针(pointer)是“指向”另外一种类型的复合类型。指针也实现了对对象的间接访问,但与引用相比也有不同:

(1)指针本身就是一个对象,允许对指针赋值和拷贝,在指针的生命周期内它可以先后指向几个不同的对象。

(2)指针无须再定义时赋初值。如果没有被初始化,将拥有一个不确定的值。

指针运算符*取地址符&

指针的类型都要和它所指向的对象严格匹配。因为引用不是对象,没有实际地址,所以不能定义指向引用的指针。

指针变量:专门用于存放指针(某个变量的地址)的变量

1
2
3
4
int c = 76;
int *pointer; //定义名字为pointer的指针变量
pointer = &c; //将变量c的地址赋值给指针变量pointer;赋值后称指针变量pointer指向了变量c
//pointer = c; //错误:因为pointer是存放地址的变量,所以只能存放地址

通过指针变量可以访问“它所指向的变量”。指针变量也是变量,是变量就有地址。

1
2
3
4
5
int c = 76;
int *pointer = &c; //*pointer为“pointer所指向的存储单元的内容",即是变量c

cout << &c <<endl; //取变量c的地址
cout << &pointer << endl; //取指针变量c的地址

赋值和指针:记住赋值永远改变的是等号左侧的对象,就能分清一条赋值语句是改变了指针还是改变了指针所指的对象的值。

1
2
3
4
int i = 42;
int *pi = 0; //pi被初始化
pi = &ival; //pi所存的地址改变,指向ival
*pi = 0; //ival的值被改变,指针pi所存的地址没有改变

&*`的运算优先级:同级

QQ图片20200125205145

空指针(null pointer)不指向任何对象。

1
2
3
int *p1 = nullptr     //C++11
int *p2 = 0; //直接将p2初始化为字面常量0
int *p3 = NULL; //需要首先#include<cstdlib>

使用未经初始化的指针是引发运行时错误的一大原因。因此建议初始化所有的指针,尽量等定义了对象之后再定义指向它的指针。

void*指针:可用于存放任意对象的地址。利用void*指针可以:拿它和别的指针比较,作为函数的输入或输出,或者赋给另外一个void*指针。不能访问其内存空间中所存的对象。

1
2
3
double obj = 3.14, *pd = &obj;
void *pv = &obj;
pv = pd;