在C++中指针通常难以理解,即使是有经验的程序员也常常因为调试指针引发的错误而备受折磨。笔者在学习C++时常常被指针弄得晕头转向,于是决定对指针的概念做一次梳理,希望本文能够对C++入门者有些许作用。
1.指针的概念
指针(pointer)是“指向(point to)”;另外一种数据类型的复合类型。与引用类似,指针也实现了对其他对象的间接访问。然而指针与引用又有区别。首先,指针本身是一个对象,即我们可以对指针进行赋值和拷贝,并且在指针的生命周期中可以先后指向几个不同的对象。其次,指针定义时不必赋值,此时指针会存在一个随机值。
2.指针的定义
定义指针类型的方法是将声明写成*d的形式,其中d为变量名,如果在一条语句中定义了几个指针变量,每个变量都必须有星号。
int *p1,*p2;//p1和p2是指向int对象的指针
double *dp1, *dp2;//dp1和dp2是指向double对象的指针
3.获取对象的地址
指针存放某个对象的地址,要想获取该地址,则需要使用取地址符&:
int a = 1;
int *p = &a;//P中存放变量a的地址,或者说p是指向a的指针
在一般情况下,指针的类型都要与他所指的对象严格匹配。
4.指针的值
指针的值应属于下列四种状态之一:
①指向一个对象,如果指针指向了一个对象,则需要使用解引用符(操作符*)来访问该对象:
int a = 1;
int *p = &a;//P中存放变量a的地址,或者说p是指向a的指针
cout << *p << endl;//由符号*得到p所指向的对象,输出42
*p=0;//由符号*得到指针p所指的对象,即可经过p给a赋值。
cout << *p << endl;//输出0
②指向紧邻对象所占空间的下一个位置
③空指针,不指向任何对象
//空指针
int *p1 = nullptr;
int *p2 = 0;
int *p3 = NULL;//三种方法等价
注意int变量直接赋值给指针是错误的操作,计时int变量的值恰好等于0也不行。
int zero = 0;
int *p4 = zero;//错误操作
④无效指针,上述以外的情况
注:在使用指针前最好初始化所有指针。这是因为,使用未经初始化的指针是引发运行时错误的一大原因:
和其他变量一样,访问未经初始化的指针所引发的后果也是无法预计的。通常这一行为将造成程序崩溃,而且一旦崩溃,想要定位到出错位置是非常棘手的。在大多数编译器环境下,如果适用了未经初始化的指针,则该指针所占内存空间的当前内容将被看做一个地址值。访问该指针,相当于访问一个本不存在的位置上的不存在的对象。糟糕的事,如果指针所占内存空间中恰好有内容,而这些内容又被当成了某个地址,我们就很难分清它到底是合法还是非法的了。
因此,建议初始化所有指针,并且尽可能在定义了对象之后定义指向他的指针。如果不清楚指针指向何方,可以初始化为空指针。
5.赋值和指针
在指针的生命周期中可以先后指向不同的对象。给指针赋值就是令他存放一个新的地址,从而指向了一个新的对象。
//赋值和指针
int i = 42;
int *pi = 0;//pi被初始化,但是没有指向任何对象
int *pi2 = &i;//pi2被初始化,指向i,即存有i的地址。
int *pi3;//pi3的值无法确定
pi3 = pi2;//pi3和pi2指向了同一个对象i
pi2 = 0;//pi2不指向任何对象
pi = &a;//pi的值被改变,指向了a
*pi = 3;//pi的指向没有改变,但a的值发生了改变
6.void指针
void指针是一种特殊类型的指针,可存放任意对象的地址。不能直接操作void*指针所指的对象,因为我们并不知道这个对象是什么类型,也就无法确定在这个对象上做哪些操作。也就是说,void指针所指的内存空间仅仅是内存空间,没办法访问内存空间中的对象。
7.指向指针的指针和指向引用的指针
通过*的个数可以区分指针的级别,两个为指向指针的指针,三个则为指向指针的指针的指针。二级指针解应用两次可以获得最原始的那个对象, 以此类推。
引用本身不是一个对象,因此不能定义指向引用的指针,但指针本身是一个对象,因此存在指针的引用
//指向指针的引用
int m = 12;
int *pp;//pp是一个int类型的指针
int *&r = pp;//r是一个对指针pp的引用
r = &m;//r引用了一个指针,因此给r赋值&m就是令pp指向了m
*r = 0;//解引用r得到m,也就是p指向的对象m变成了0
8.指针和const
指向常量的指针不能用于改变其指向对象的值,要想存放常量对象的地址,只能使用指向常量的指针。
const double pi=3.14;//pi是一个常量
double *ptr=π//错误,ptr是一个普通的指针,无法指向常量
const double *cptr=π//正确,cptr可以指向一个双精度常量
*cptr=42;//错误,无法给*cptr赋值
在本文第三点中提到一般而言指针的类型要与其只想的对象严格匹配,但有两种特殊情况。第一种特殊情况就是,允许令一个指向常量的指针指向一个非常量对象:
double dval=3.14;
cptr=&dval;//正确,但是不能通过*cptr改变dval的值
const指针
指针是一个对象, 因此允许将指针本身定为常量。常量指针必须初始化,而且一旦初始化完成,他的值(存放在指针中的那个地址)就不能再改变了
int e=0;
int *const c=&e;//c将一直指向e
const double pi=3.14;
const double *const pip=π//pip是一个指向常量对象的常量指针
原文链接:https://blog.csdn.net/m0_46691785/article/details/107675480