底层const顶层const
首先顶层const和底层const的说法和指针有很大的关系。指针本身是一个对象,但它又指向另一个对象,这就是指针的两种属性。
- 对于指针本身是一个常量,即指针的指向是一个常量,也就说不能改变指针的指向,称其为顶层const属性;
- 对于指针指向的对象是一个常量,即指针指向的地址的值是一个常量,也就是说不能改变指针指向内存的值,称其为底层 const属性。
在代码表现上是:
int* cosnt p1 = &a;
//p1是顶层const
cosnt int* p2 = &a;
//p2是底层const
区分很简单,看const修饰的是哪个。前者修饰的是p1,即指针本身,所以为顶层属性;后者修饰的*p2,即指针的指向地址的值,所以为底层属性。p1又称为常量指针,p2又称为指向常量的指针。
下面请判断表达式赋值是否正确?
int a = 2,
int *p = &a;
(1)const int *p1 = p;
(2) int * const p2 = p;
(1)和(2)均正确,因为int* 型可以转化为底层const(const int *)或顶层const(int * const)
(3) int * const p3 = p1;
(4) const int * p4 = p2;
(3)为错误,因为p1为底层const,在赋值时不能忽略此属性,而p3为顶层const
(4)正确,尽管p2为顶层const,但是赋值时忽略顶层const属性,忽略后为int*,可以转换为顶层const,这就和(1)情况相同。
(5) int * p5 = p1;
(6) int * p6 = p2;
(5)为错误,原因和(3)一样,p1为底层const,在赋值时不能忽略此属性。
(6)正确,原因和(4)一样,p2为顶层const,但是赋值时忽略顶层const属性
(7)const int* const p7 = p1;
(8)const int* const p8 = p2;
上述两式均正确。(7)正确是因为p7有底层const属性
(9)const int* p10 = p7;
(10) int* const p11 = p7;
显然(9)式正确,(10)式不正确。因为p7忽略顶层const属性后,还有底层const属性,所以(10)式是无法匹配的。
补充:
const int b =3;
const int *pb = &b;//此时&b相当于const int*,只能初始化底层const。写成int *或int const*均会报错
总结:
- 顶层const在赋值给其他变量时,可以忽略顶层属性;
- 底层const在赋值给其他变量时,不能忽略底层属性;
- int*类型可以转换为顶层和底层const,所以它可以给顶层和底层的const赋值;
- 底层const无法转换为顶层const。
参考:
《C++ Primer 第5版》2.4.3
如果有疑问,欢迎评论区下方留言;本人水平有限 ,如有错误,也欢迎在评论区下方批评指正。若是喜欢本文,就帮忙点赞吧!