复合类型之指针
指针的含义
指针是“指向”另外一种类型的复合类型。与引用类似,指针也实现了对其他对象的间接访问。
指针和引用的区别
(1)指针是一个对象,允许对指针赋值和拷贝,而且指针在其生命周期内可以先后指向几个不同的对象;
(2)指针无需在定义时赋初值。和其他内置类型一样,在块作用域内定义的指针如果没有进行初始化操作,系统也将会自动分配一个不确定的值。
指针的定义
定义指针类型的方法将声明符写成*d的形式,其中d是变量名,定义如下所示:
int *ip1,*ip2; //ip1和ip2都是指向int 型对象的指针
double *dp1,*dp2;//dp1和dp2都是指向double 型对象的指针
获取对象的地址
指针存放某个对象的地址,要想获取该地址,需要使用取地址符(&),代码如下所示:
int ival=42;
int *p=&ival;//p存放变量ival的地址
注:一般情况下,指针的类型和它所指向的对象需要严格匹配:
double dval;
double *pd=&dval;//正确
double *pd2=pd; //正确
int *pi=pd //错误,指针pi和pd的类型不匹配
pi=&dval; //错误
这是因为在声明语句中指针的类型实际上被用于指定它所指向对象的类型,所以二者之间必须匹配。
特例1:
但是,我们可以令一个指向常量的指针指向一个非常量对象:
即定义如下:
const double *ptr=nullptr;
double dval=3.14;
ptr=&dval;//合法,但是不能通过ptr修改dval的值,但是dval的值还是可变的。
利用指针访问对象
如果指针指向了一个对象,则允许使用解引用(*)来访问该对象;
同时,需要注意,解引用操作仅仅适用于那些确实指向了某个对象的有效指针
空指针
空指针不指向任何对象,在试图使用一个指针之前可以首选检查它是否为空。空指针生成的方法如下:
int *p1=nullptr; //C++11新引入
int *p2=0; //直接将p2初始化为字面常量0
int *p3=NULL; //预处理变量
其实,第二种和第三种定义方式是一样的,参见http://blog.csdn.net/u013266600/article/details/78180641
注:
把int变量直接复制给指针是错误的操作,即使int变量的值恰好等于0也不可以:
int i= 0;
int *p=i; //错误:不能把int变量直接赋值给指针
void* 指针
void* 是一种特殊的指针类型,可用于存放任意对象的地址。一个void * 指针存放了一个地址,但是,对该地址中到底是个什么类型的对象并未了解。
double obj=3.14,*pd=&obj;//正确
void *pv =&obj;//obj 可以使任意类型的对象
pv=pd;//pv可以存放任意类型的指针
利用void * 指针可以做的事很有限:和别的指针进行比较,作为函数的输入或者输出,或者赋值给另外一个void*指针。但是我们无法直接操作void* 指针所指的对象,因为不知道该变量是什么类型,不知道可以进行哪些操作。
指针和const
const 和指针结合,会有什么样的火花呢?
const int *p;//*p在const右侧,所以*p不可变,但是p可变
int const *p;//*p在const右侧,所以*p不可变,但是p可变
int *const p;//p在const右侧,所以p不可变,但是*p可变
const int *const p;//p在const右侧,所以p不可变,*p在const 右侧,所以*p不可变
查看以下代码:
const double pi=3.14;
double *ptr=π//错误,ptr是一个普通指针,如果合法,则可以随意修改pi的值,但是pi 定义为常量不可更改,所以相互矛盾,出现错误
const double *cptr=π//正确:cptr可以指向一个双精度常量
*cptr=42;//错误,在上面的定义中,*cptr在const 的右侧不可变,所以不可以赋值
上一篇: SpringBoot整合JSP页面,java -jar方式启动
下一篇: Django-查询优化