顶层const和底层const

什么是 顶层const底层const

顶层const:表示指针是一个常量。
底层const:表示指针所指向的对象是一个常量。

1、例子

指针中const

const int *const p = new int(10); 

第一个const是底层const ,第二个是顶层const。

普通变量中const

const int a = 10;
int const b = 10;

因为是普通变量所以不区分顶层或是底层const,不论const的位置在哪,都声明了这个变量不允许被修改。

引用中的const

const int ci = 10;
const int& c = ci;

用于声明引用的const都为底层const

2、原因

当执行对象的拷贝操作时,常量是顶层const还是底层const的区别明显。其中顶层const可以忽略,但是底层const不能忽略

我们进行分析:

const int *const p = new int(10);
int *p1 = p;
int *const p2 = p;
const int *p3 = p;

如下所示,我们忽略所有的顶层const:

const int* p = new int(10);
int *p1 = p;    //error:类型不一致
int *p2 = p;    //error:类型不一致
const int *p3 = p;  //right:变量类型一致

其次我们继续观察:

const int* p = new int(10);
int *p1 = p;    //error

此处我们未修饰p的指向,但是使用了const修饰了p的值。
如果第二句可以执行,我们可以接着执行这一句 * p1 = 10。那么
p的值也会发生改变,这和我们开始约定的 const int* p出现了冲突,所以出现错误。

还有一个容易出现的误区:

const int a = 10;
int *p4 = &a;   //error

这里 &a存放的是a的地址,const修饰a的值不可改变,但是没有说明a的地址不可以改变。我们将它看作一个指针,也就是a的地址可以进行改变,a中存放的内容不可改变。也就间接的可以看作是一个底层const修饰的 &a。底层const不可忽略,所以出现问题。
改正如下:

const int a = 10;
const int *p4 = &a; //同样是顶层const修饰

引用中的const



    int &r3 = r1;
    int &r4 = 40;

原则:

  • 引用不是对象且不会拷贝,所以和顶层const或者底层const的逻辑不通用
  • 常量引用如果在左侧,那么右侧可以接任何东西。
int *p1 = &c;
const int *p2 = &c;
const int *const p3 = &c;

const int &r1 = 20;
const int &r2 = *p1;
const int &r3 = *p2;
const int &r4 = *p3;
  • 非常量引用 = 常量 ×
int &r5 = 10;   //error
  • 引号在等号右侧时,忽略&
const int &r6 = 10;
int &r7 = r6;

//忽略等号右侧的&
int &r7 = const int r6;     //error:类型不匹配
  • 非常量 = 常量引用 √
int b = r6;
posted @ 2024-05-07 12:00  baobaobashi  阅读(62)  评论(0编辑  收藏  举报