所以,指向常量的指针也没有规定其所指的对象必须是一个常量,所谓指向常量仅仅要求不能通过该指针修改所指向对象的值,而没有规定所指对象的值不能通过其他途径改变
const double homo = 1.14; const double *cptr = &homo; cout << "cptr = " << *cptr <<endl double dval = 5.14; cptr = &dval; //允许一个 指向常量的指针 指向 一个非常量对象 //*cptr = 0.0 //但是不允许通过 指向常量的指针 修改非常量对象的值 cout << "cptr = " << *cptr <<endl; dval = 0.0 //所指对象的值可以通过其他途径改变 cout << "cptr = " << *cptr <<endl;现在我们输出就变成了:
cptr = 1.14
cptr = 5.14
cptr = 0
和引用不同,指针本身是对象,所以允许把指针本身定为常量,也就是常量指针,常量指针必须被初始化,并且初始化完成后值(存放在指针对象里的地址)不能改变
把*放const关键字之前,用以说明指针是一个常量(即不变的是指针本身的值)
int errorNumb = 0; int* const curErr = &errorNumb; //curErr是一个常量指针,一直指向errNumb const double pi = 3.1415; const double* const pip = π //pip是一个 指向常量对象 的 常量指针以下两种写法区别很大:
int* const curErr = &errorNumb; //curErr一直指向errNumb *curErr = 1; //可以修改所指变量的值 const int* curErr = &errorNumb; //curErr是一个 指向常量的指针 *curErr = 1; //× 不能通过curErr修改所指对象的值 顶层const和底层const#由于指针本身是一个对象,它又可以指向另外一个对象,因此指针本身是不是常量和指针所指的对象是不是常量就是两个互相独立的问题,顶层const表示指针本身是个常量,底层const表示指针所指的对象是个常量
顶层const其实可以表示任意的对象(自身)是常量,指针式比较特殊的,因为它既可以是顶层也可以是底层const
int i = 0; int* const p1 = &i; //p1本身是常量,顶层const const int ci = 42; //ci本身是常量,顶层const const int* p2 = &ci; //*在const之后,p2是指向常量的指针,底层const const int* const p3 = p2; //先看左边是顶层,再看右边是底层,p3是指向常量的常量指针 const int& r = ci; //声明引用的const都是底层const,r是一个对常量的引用拷贝操作不会影响被拷贝对象的值,顶层const不受影响
i = ci; p2 = p3;但是底层const就会产生限制:
拷贝操作时,拷入和拷出的对象必须有相同的底层const资格,活着两个对象数据类型能转换(非常量能转成常量,反之不行)
int* p = p3; //× p3包含底层const,p没有 const int* p = p3; //√ p和p3都是底层const p2 = p3; //√ p2和p3都是底层const p2 = &i; //√ int能转换成const int* int& r = ci; //× 普通int&不能绑到const int&上 const int& r2 = i; //√ const int&可以绑到一个普通int上