const与指针
当const
限定符与指针结合的时候,经常会让人迷惑。本文根据《C++ Primer》上给出的一些解释谈谈自己的理解:
指向常量的指针(pointer to const)
先来看一则书上的示例:
const double pi = 3.14; // pi是个常量,它的值不能改变
double *ptr = π // 错误:ptr是一个普通指针
const double *cptr = π // 正确:cptr可以指向一个双精度常量
*cptr = 42; // 错误:不能给 *cptr 赋值
double dval = 3.14; // dval是一个双精度浮点数,它的值可以改变
cptr = &dval; // 正确:但是不能通过cptr改变dval的值
- 上述示例中,
cptr
就是一个指向常量的指针,不能用于改变指向的对象的值。 - 而要存放一个常量的地址,只能使用指向常量的指针。
- 但是可以将一个非常量
dval
的地址赋值给cptr
,根据书上的解释,这里可以理解为,指针cptr
会“自以为”指向了常量,所以不能通过该指针去改变其指向的值。
指针常量(const pointer)
同样先来看一则书上的示例:
int errNumb = 0;
int *const curErr = &errNumb; // curErr将一直指向errNumb
const double pi = 3.14159;
const double *const pip = π // pip是一个指向常量对象的指针常量
- 这里我对const pointer采取的翻译是“指针常量”而不是书中的“常量指针”。因为我觉得,const pointer就是一个常量,其类型是一个指针,所以称“指针常量”可能比较符合我个人对其具体含义的理解。
- 而“常量指针”应该理解为上文提到的“指向常量的指针”。
- 上面的例子中
curErr
的例子说明,curErr
指向的可以是变量,但是这个指针本身是个常量。 - 而比较难以理解的是
pip
这个例子,书上给出的一种理解方式是,从右向左阅读:- 变量名
pip
左边是const
,说明pip
是个常量 - 再向左看是
*
,说明pip
是个指针,这就可以说pip
是个指针常量。指针的值不能改变。 - 接着是
const double
,说明指针常量pip
指向的是一个双精度常量。pip
所指向的对象不能改变。
- 变量名
- 所以可以说,
pip
既是一个常量指针又是一个指针常量。
与类型别名的联系
在类型别名部分,也有一个与const和指针相关的例子:
typedef char *pstring;
const pstring cstr = 0; // cstr是指向char的常量指针
而在理解cstr
的类型的时候,不能简单将其声明语句理解为:
const char *cstr = 0;
后者数据类型是char
,*
成为了声明符的一部分,const char
成了基本的数据类型。
前后两种声明的含义是不同的,前者声明了一个指向char
的指针常量,后者声明了一个指向const char
的常量指针。
参考书目
- C++ Primer(中文第5版)