顶层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;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?