复合类型(2)——指针
前言
指针——备受折磨
指针的定义
int *ip1, *ip2; //ip1和ip2都是指向int型对象的指针
double dp, *dp2; //dp2是指向double型对象的指针,dp是double型对象
指针与引用的不同点:
1.指针本身就是一个对象,允许对指针赋值和拷贝,而且在指针的生命周期内它可以先后指向几个不同的对象。
2.指针无须在定义时赋初值。和其他内置类型一样,在块作用域内定义的指针如果没有被初始化,也将拥有一个不确定的值。
获取对象的地址
指针存放某个对象的地址,要想获取该地址,需要使用取地址符(&)
int ival=42;
int *p=&ival; //p存放变量ival的地址,或者说p是指向变量ival的指针
所有指针的类型都要和它所指向的对象严格匹配
例外
(1)允许令一个指向常量的指针指向一个非常量对象
double dval=3.14;
const double *cptr=&dval;//正确,但是不能通过cptr改变dval的值
(2)基类与派生类
见复合类型(1),同引用
指针值
指针的值(即地址)应属下列4种状态之一:
1.指向一个对象
2.指向紧邻对象所占空间的下一个位置
3.空指针,指针没有指向任何对象
4.无效指针,上述情况之外的其他值
利用指针访问对象
如果指针指向了一个对象,则允许使用解引用符(操作符*)来访问该对象。
int ival=42;
int *p=&ival;
cout<<*p;//输出42
如果给解引用的结果赋值,实际上也就是给指针所指的对象赋值
*p=0;//由p给变量ival赋值
cout<<*p;//输出0
空指针
不指向任何对象
生成空指针的方法如下:
int *p1=nullptr;//等价于int *pi=0;
int *p2=0;//直接将p2初始化为字面常量0;
//需要首先#include cstdlib
int *p3=NULL;//等价于int *p3=0;
建议:初始化所有指针,实在不清楚指向何处的,初始化为nullptr或0
int zero=0;
pi=zero;//错误,不能把int变量直接赋值给指针
赋值和指针
给指针赋值就是令它存放一个新的地址,从而指向一个新的对象。
int i=42;
int *pi=0;//pi被初始化,但没有指向任何对象
int *pi2=&i;//pi2被初始化,存有i的地址
pi2=0;//现在pi2不指向任何对象了
赋值,永远改变的是等号左侧的对象
pi=&ival;//pi的值被改变,现在pi指向了ival
*pi=0;//ival的值被改变,指针pi并没有改变
其他指针操作
int ival=1024;
int *pi=0;//pi合法,空指针
int *pi2=&ival;//pi2为合法指针,存放着ival的地址
if(pi) //pi的值是0,因此条件的值是false
//...
if(pi2) //pi2指向ival,因此它的值不是0,条件的值是true
//...
任何非0指针对应的条件值都是true。
两个指针存放的地址值相同(两个指针相等)有三种可能:
1.都为空
2.都指向同一对象
3.都指向同一对象的下一地址
一个指针指向某对象,同时另一个指针指向另外对象的下一地址,也可能出现指针相等。
void* 指针
可用于存放任意对象的地址
double obj=3.14, *pd=&obj;
//正确:void*能存放任意类型对象的地址
void *pv=&obj; //obj可以是任意类型的对象
pv=pd; //pv可以存放任意类型的指针
不能直接操作void*指针所指的对象,因为我们并不知道这个对象的类型。