有两种不同的方式将const关键字用于指针:
第一种是指针指向一个常量对象,防止使用该指针修改所指向的值;
第二种是将指针本身声明为常量,防止改变指针指向的位置。
1.指向一个常量的指针
例如,声明一个指向常量的指针pt:
int age=23;
const int*pt=&age;
该声明指出,pt指向一个const int(这里为23),因此不能使用pt来修改这个值,即*pt的值为const,不能被修改:
*pt+=1; //INVALID
但是pt的声明并不意味着它指向的值是一个常量,而只是意味着对pt而言这个值是常量,例如:pt指向age,而age不是const,可以直接通过age变量来修改age的值,但不能使用const指针来修改它:
*pt=20; //INVALID
age=20; //VALID
2.将const变量的地址赋给指向const的指针是可行的,但将const的地址赋给常规指针是不可行的:
const int age=23;
const int*pt=&age; //VALID
const int age=23;
int*pt=&age; //INVALID
第一种情况禁止使用age来修改值23,也不能使用pt来修改;
第二种情况不可行的原因是将常量age的地址赋值给pt。则可以使用pt来修改age的值,这就使得age的const状态很荒谬,因此C++禁止将const的地址赋给非const指针,如果非要这么做,只能使用强制转换来突破这种限制。
3.指针指向指针
当涉及为一级间接关系,则将非const指针赋给const指针是可以的:
int age=23; //age++is a valid operation
int*pd=&age; //*pd=24 is a valid operation
const int*pt=pd; //*pt=25 is a invalid operation
注意:如果数据类型本身并不是指针,则可以将const数据或非const数据的地址赋给指向const的指针,但只能将非const数据的地址赋给非const指针。
4.将指针声明为const常量
int sloth=3;
const int*pt=&sloth; //a pointer to const int
int *constfinger=&sloth; //a const pointer to int
第二种声明格式只能使finger指向sloth,不能修改指针指向的地址,但允许使用finger来修改sloth的值,第一种声明格式不允许使用pt来修改sloth的值,但允许修改pt指向的地址,简而言之,finger和*pt是const,而*finger和pt不是。
补充:
指针本身是一个对象,它又可以指向另外一个对象,故指针本身是不是常量以及指针所指的对象是不是一个常量是两个相互独立的问题,可以用名词顶层const(top-level const)表示指针本身是一个常量,名词底层const(low-level const) 表示指针所指对象时一个常量;
int i=0;
int *const p1=&i; //不能改变p1的值,顶层const
const int ci=42; //不能改变ci的值,顶层const
const int *p2=&ci; //允许改变p2的值,底层const
const int *const p3=p2;//靠右的const是顶层const,靠左的是底层const
const int &r=ci; //用于声明引用的const都是底层const
说明:作为学习C/C++过程中的笔记,内容摘录《C++ Primer Plus》第六版