最近复习C++prime第六章,看到书上写的顶层const/底层const那一块的时候,感觉自己又乱了,第一次看时感觉自己看懂了,过了几个月,回过头来看时又看不懂了,结合网上的资料,总结一下;
顶层const
所谓的顶层const,就是经过const修饰后的变量保持不变:
const int m =8; //m的值不再变化
int *const ptr1=&m; //ptr1始终指向m,不能再指向别的变量;
int b=m; //拷贝时,忽略顶层的const;
int *const ptr2=&b; // ptr2始终指向b,但是b的值可以改变;
底层const
所谓的底层const, 一般是修饰指针对象,经修饰之后该指针必须指向对应的常量,即指向常量的指针:
const int a=20;
const int *p=&a; //此时const 修饰的是*p,也就是a,所以不能通过改变*p的值来改变a的值;
int n=9;
const int *p2=&n; //正确,非常量可以转换为常量;
总结:
1.顶层const与底层const的概念;
指针本身是一个对象,因为,指针实际对应着内存单元的一段存储空间,然而,指针所指向的也是一个数据对象,
因此,指针是一个常量与指针所指向的是一个常量是两个完全不同的概念,
顶层 const 表示的是指针本身是一个常量, 底层const 表示的是指针所指的对象是一个常量.
2.顶层const与底层const在执行拷贝操作时的不同
(1)顶层const不受什么影响
int i=0;
const int j =21; //j的值不能改变,这是一个顶层const;
i=j; // 正确,j是一个顶层const,拷贝无影响;
const int *p=&j; //底层const;
const int *const p3 = p; // 靠右的 const 是顶层 const ,靠左的是底层 const
p=p3; // 正确,p2和p3指向的对象类型相同,p3的顶层const不影响拷贝.
(2)底层const的限制不能忽略
要求拷出和拷入的对象有相同的底层const资格或者能转换为相同的数据类型,一般非常量能够向常量转换,反之则不行.
int *q=p3; //错误:p3包括底层const定义,而p没有.
p=p3; // 正确,p和p3都是底层const.
p=&i; //正确.int *能转换为const int *;(非常量能转换为常量);
int &r=ci; //错误,普通的int &不能绑定到int常量上.
const int &r2=i; //正确.const int &可以绑定到一个普通int上;(非常量转换为常量);
分析上面的代码:
int *q=p3;
p3既是一个顶层const又是一个底层const,在执行对象拷贝时,顶层const部分没有任何影响,完全不用考虑,但是p3又是一个底层const,
它要求拷入的对象有相同的底层const资格, 而p没有,所以是错的.
p=p3;
p3要求拷入的对象拥有相同的底层const资格,p2也是一个底层const, 故正确.
p2 = &i;
对 i 取地址将得到 int*, p2 是 const int*,前者是非常量,后者是常量,赋值语句等号右侧的类型向左侧转换,非常量能够向常量转换,故正确;
int &r = ci;
由左侧部分我们知道,需要得到的是一个绑定到 ci 上的引用,而绑定到 ci 上的引用的类型是 const int&,等号左侧的类型是 int&,赋值语句等号右侧的类型向左侧转换,
但是常量不能向非常量转换,所以是错误的;
const int &r2=i;
由左侧部分我们知道,需要得到的是一个绑定到i上的引用,而绑定到i上的引用的类型是const int &,而i的类型是int 型,所以非常量i转换为常量i.