文章目录
前言
去年在脑子里面总结过顶层const与底层const,指针常量和常量指针这部分内容,始终没有文字记录,今天记下来以后随时可以看,也可以知道当下对这块知识的了解程度。
一、顶层const与底层const
顶层const与底层const是C++中用于区分常量修饰位置的重要概念,核心区别在于const修饰的对象是“自身”还是“指向/引用的内容”。
Ⅰ、基本定义
| 类型 | 含义 | 核心特征 |
|---|---|---|
| 顶层const | 修饰对象本身为常量 | 对象自身不可修改 |
| 底层const | 修饰对象指向/引用的内容为常量 | 指向/引用的内容不可修改,对象本身可修改(指针场景) |
Ⅱ、具体场景分析
1. 普通变量(仅顶层const)
对于非指针/引用的普通变量,const只能修饰变量自身,因此只有顶层const。
const int a = 10; // 顶层const:a本身是常量,不可修改
int const b = 20; // 等价于const int b,同样是顶层const
2. 指针(同时支持顶层+底层const)
指针是复合类型,const的位置决定了修饰的是指针本身还是指针指向的内容。
| 语法形式 | 修饰对象 | const类型 | 示例解释 |
|---|---|---|---|
const int* p | 指向的内容(int) | 底层const | p可以指向其他地址,但*p(指向的内容)不可修改 |
int const* p | 指向的内容(int) | 底层const | 与const int*等价,仅写法不同 |
int* const p | 指针本身(int*) | 顶层const | p指向的地址不可修改,但*p(指向的内容)可修改 |
const int* const p | 指向的内容 + 指针本身 | 底层+顶层const | p既不能改指向,*p也不能改内容 |
3. 引用(仅底层const)
引用本质是对象的“别名”,引用本身不可被重新绑定(天生顶层const),因此const只能修饰引用的内容,即底层const。
const int& r = a; // 底层const:r引用的内容(a)不可修改
int& const r = a; // 非法!引用本身不可修改,无需显式加const
Ⅲ、关键规则
1. 类型转换(底层const的兼容性)
-
允许:将非const对象的地址/引用赋值给带底层const的指针/引用(安全,避免修改)。
例如:int a = 10; const int* p = &a;(p指向a,但不能通过p修改a)。 -
禁止:将const对象的地址/引用赋值给不带底层const的指针/引用(危险,可能破坏const)。
例如:const int b = 20; int* q = &b;(错误!q可能修改b,违反const语义)。
2. 赋值操作(顶层const的忽略)
赋值时,顶层const会被忽略(只关心值,不关心变量是否为常量),但底层const必须兼容。
const int a = 10; // 顶层const
int b = a; // 允许:a的顶层const被忽略,值10赋给b
const int* p = &a; // 底层const
int* q = p; // 禁止:p是底层const(指向const内容),q无底层const,类型不兼容
Ⅳ、总结记忆法
- 顶层const:const修饰“变量名”或“指针名”本身,例如
int* const p(p是常量指针)。 - 底层const:const修饰“指向的类型”,例如
const int* p(p指向常量)。 - 指针可同时有顶层+底层const,引用只有底层const。
通过具体例子和规则对比,能更清晰地理解两者的区别。你可以结合代码实践进一步验证~
二、指针常量与常量指针
指针常量与常量指针是C++中指针的两种常见修饰形式,核心区别在于**const修饰的是“指针本身”还是“指针指向的内容”**。以下从定义、语法、特点、示例等维度详细对比:
Ⅰ、基本定义
| 术语 | 核心含义 | 本质(结合顶层/底层const) |
|---|---|---|
| 常量指针 | 指针指向的内容是常量(不可通过指针修改) | 底层const(修饰指向的类型) |
| 指针常量 | 指针本身是常量(指针的指向不可修改) | 顶层const(修饰指针变量本身) |
Ⅱ、语法形式与对比
语法的关键:const与*的相对位置
const在*左侧:修饰指向的内容(常量指针);const在*右侧:修饰指针本身(指针常量)。
1. 常量指针(指向常量的指针)
语法:const 类型* 指针名 或 类型 const* 指针名(两种写法等价)。
特点:
- 指针可以改变指向(指向不同的地址);
- 但不能通过该指针修改指向的内容(指向的内容被
const保护)。
示例:
int a = 10;
int b = 20;
const int* p = &a; // 常量指针:p指向a,指向的内容(a)不可通过p修改
p = &b; // 允许:p可以改变指向,指向b
// *p = 30; // 错误:不能通过p修改指向的内容(b),因为p是常量指针
2. 指针常量(指针类型的常量)
语法:类型* const 指针名。
特点:
- 指针不能改变指向(初始化后必须固定指向一个地址);
- 但可以通过该指针修改指向的内容(如果指向的对象本身不是
const)。
示例:
int a = 10;
int b = 20;
int* const p = &a; // 指针常量:p的指向固定为a的地址,不可修改
// p = &b; // 错误:p是指针常量,不能改变指向
*p = 30; // 允许:可以通过p修改指向的内容(a变为30)
Ⅲ、混合修饰:既常量指针又指针常量
当指针同时被const修饰指向的内容和指针本身时,它既是常量指针又是指针常量。
语法:const 类型* const 指针名。
特点:
- 指针不能改变指向(指针常量的特性);
- 也不能通过指针修改指向的内容(常量指针的特性)。
示例:
int a = 10;
const int* const p = &a; // 混合const:p既不能改指向,也不能改内容
// p = &b; // 错误:指针本身是常量,不能改指向
// *p = 30; // 错误:指向的内容是常量,不能改内容
Ⅳ、常见误区与澄清
-
术语字面混淆:
中文术语“常量指针”容易被误解为“常量的指针”(即指向常量的指针,实际正确),而“指针常量”是“指针类型的常量”(指针本身是常量)。不要通过字面顺序判断,而要通过const与*的位置。 -
与引用的对比:
引用本质是“对象的别名”,引用本身不可被重新绑定(天生是“指针常量”),因此引用只有“常量引用”(即const 类型&,对应底层const,指向常量),没有“引用常量”的说法。
Ⅴ、记忆技巧
-
口诀法:
左定值,右定向const在*左:定内容(指向的内容不可修改,即常量指针);const在*右:定指向(指针的指向不可修改,即指针常量)。
-
语法拆解法:
const int* p:const修饰int(指向的类型)→ 指向常量的指针;int* const p:const修饰int*(指针类型)→ 指针是常量。
Ⅵ、总结
| 类型 | 语法形式 | 指向可改? | 内容可改?(通过指针) | 示例代码 |
|---|---|---|---|---|
| 常量指针 | const int* p | ✅ 可改 | ❌ 不可改 | const int* p = &a; p = &b; |
| 指针常量 | int* const p | ❌ 不可改 | ✅ 可改(对象非const时) | int* const p = &a; *p = 30; |
| 混合const | const int* const p | ❌ 不可改 | ❌ 不可改 | const int* const p = &a; |
通过语法位置和实际示例,能更清晰地理解两者的区别。建议结合代码实践加深记忆~
三、对应关系
对于指针这种复合类型来说,底层const就是常量指针,顶层const就是指针常量
在指针的上下文中,这种对应关系是成立的,但需要明确术语的准确含义,避免混淆:
Ⅰ、术语对应关系(仅针对指针)
| const类型 | 指针术语 | 语法示例 | 核心含义 |
|---|---|---|---|
| 底层const | 常量指针 | const int* p 或 int const* p | 指针指向的内容是常量(不可通过指针修改) |
| 顶层const | 指针常量 | int* const p | 指针本身是常量(指针的指向不可修改) |
Ⅱ、为什么对应关系成立?
-
常量指针:重点在“指向常量”,即
const修饰的是指针指向的类型(int),因此是底层const。
例如:const int* p→p可以指向不同地址,但*p(指向的内容)不可修改。 -
指针常量:重点在“指针是常量”,即
const修饰的是指针本身(int*),因此是顶层const。
例如:int* const p→p的指向固定(不可修改),但*p(指向的内容)可以修改(如果指向的对象本身非const)。
Ⅲ、注意事项
-
术语的局限性:
“常量指针”和“指针常量”是指针特有的术语,而顶层const/底层const是更通用的概念(可用于非指针类型,如const int a是顶层const)。 -
混合const的情况:
指针可以同时具有顶层+底层const,例如:const int* const p; // 既有底层const(指向常量),又有顶层const(指针本身是常量)此时
p既是常量指针(指向常量),又是指针常量(指针本身是常量)。
Ⅳ、总结
在指针场景下,底层const对应“常量指针”,顶层const对应“指针常量”,这种说法是正确的。但建议结合语法位置理解本质:
- 底层const:
const在*左侧(修饰指向的内容); - 顶层const:
const在*右侧(修饰指针本身)。
这样记忆更不容易出错,也能推广到其他复合类型~
总结
这是我理想中知识点记录的效果,真的非常满意这种记录结果,清晰透彻,希望以后的文章也可以这样不再啰里啰唆,绕来绕去讲不清楚。
675

被折叠的 条评论
为什么被折叠?



