1. 存放常量对象的地址,只能使用指向常量的指针,即非常量指针不能指向常量对象;
const double pi = 3.14; //正确,pi是个常量,它的值不可变
const double *pi1 = 3.14; //错误,pi1不能指向一个字面常量,应该指向一个常量对象,但若右值是0,即指向空指针可以。
double *ptr = π //错误,ptr不是常量指针,而pi是一个常量
const double *cptr = π //正确,cptr可以指向一个双精度常量
*cptr = 42; //错误,不能给*cptr赋值
//const double *cptr; //正确,可以不初始化,但是无效指针。
2. 虽然要求指针的类型必须与其所指对象的类型一致,但是有两个例外,其一就是允许一个指向常量的指针指向一个非常量对象(其实就是左值的限定符要包含右值的限定符 );
double dval = 3.14; //正确,dval是一个非常量
cptr = &dval; //正确,但是不能通过cptr改变dval的值,dval可以通过其他方式改变自己的值。
/*
同时,此处cptr更换了指向的对象,从先前指向的pi变成了现在了dval,可以看出这是与常量引用最重要的一点,常量引用无法更换绑定的对象,但是指针可以。
*/
3.常量指针
常量指针必须初始化,而且一旦初始化结束后,则它的值(存放的地址值)就不能再改变了,即不能再指向其他对象(不能再次调用赋值运算符)。
书写时将*放在const关键字的前面就代表着指针是一个常量,不变的是指针本身的值而非指向的那个值。
int errNumb = 1;
int *const curErr = &errNumb; //正确,且必须进行初始化,常量指针可以指向非常量对象地址,curErr将一直指向errNumb。
const double pi = 3.14;
const double *const pip = π
/*
以上一行代码正确,pip是一个指向常量对象的常量指针。
对于这些复杂的限定符,比如,pip,可以采用从右到左的方式来阅读,先看*const代表着pip是一个常量指针,再看const double代表着pip指向的对象是一个双精度浮点型常量。
*/
*pip = 3.72; //错误,pip指向的对象是一个常量,不可改变
*curErr = 0; //正确,将curErr所指向的对象的值变为0,即errNumb为0