顶层const与底层const,指针常量和常量指针


前言

去年在脑子里面总结过顶层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底层constp可以指向其他地址,但*p(指向的内容)不可修改
int const* p指向的内容(int底层constconst int*等价,仅写法不同
int* const p指针本身(int*顶层constp指向的地址不可修改,但*p(指向的内容)可修改
const int* const p指向的内容 + 指针本身底层+顶层constp既不能改指向,*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;    // 错误:指向的内容是常量,不能改内容

Ⅳ、常见误区与澄清

  1. 术语字面混淆
    中文术语“常量指针”容易被误解为“常量的指针”(即指向常量的指针,实际正确),而“指针常量”是“指针类型的常量”(指针本身是常量)。不要通过字面顺序判断,而要通过const*的位置

  2. 与引用的对比
    引用本质是“对象的别名”,引用本身不可被重新绑定(天生是“指针常量”),因此引用只有“常量引用”(即const 类型&,对应底层const,指向常量),没有“引用常量”的说法。

Ⅴ、记忆技巧

  • 口诀法左定值,右定向

    • const*定内容(指向的内容不可修改,即常量指针);
    • const*定指向(指针的指向不可修改,即指针常量)。
  • 语法拆解法

    • const int* pconst修饰int(指向的类型)→ 指向常量的指针;
    • int* const pconst修饰int*(指针类型)→ 指针是常量。

Ⅵ、总结

类型语法形式指向可改?内容可改?(通过指针)示例代码
常量指针const int* p✅ 可改❌ 不可改const int* p = &a; p = &b;
指针常量int* const p❌ 不可改✅ 可改(对象非const时)int* const p = &a; *p = 30;
混合constconst int* const p❌ 不可改❌ 不可改const int* const p = &a;

通过语法位置和实际示例,能更清晰地理解两者的区别。建议结合代码实践加深记忆~

三、对应关系

对于指针这种复合类型来说,底层const就是常量指针,顶层const就是指针常量
在指针的上下文中,这种对应关系是成立的,但需要明确术语的准确含义,避免混淆:

Ⅰ、术语对应关系(仅针对指针)

const类型指针术语语法示例核心含义
底层const常量指针const int* pint const* p指针指向的内容是常量(不可通过指针修改)
顶层const指针常量int* const p指针本身是常量(指针的指向不可修改)

Ⅱ、为什么对应关系成立?

  • 常量指针:重点在“指向常量”,即const修饰的是指针指向的类型int),因此是底层const
    例如:const int* pp可以指向不同地址,但*p(指向的内容)不可修改。

  • 指针常量:重点在“指针是常量”,即const修饰的是指针本身int*),因此是顶层const
    例如:int* const pp的指向固定(不可修改),但*p(指向的内容)可以修改(如果指向的对象本身非const)。

Ⅲ、注意事项

  1. 术语的局限性
    “常量指针”和“指针常量”是指针特有的术语,而顶层const/底层const是更通用的概念(可用于非指针类型,如const int a是顶层const)。

  2. 混合const的情况
    指针可以同时具有顶层+底层const,例如:

    const int* const p;  // 既有底层const(指向常量),又有顶层const(指针本身是常量)
    

    此时p既是常量指针(指向常量),又是指针常量(指针本身是常量)。

Ⅳ、总结

在指针场景下,底层const对应“常量指针”,顶层const对应“指针常量”,这种说法是正确的。但建议结合语法位置理解本质:

  • 底层const:const*左侧(修饰指向的内容);
  • 顶层const:const*右侧(修饰指针本身)。

这样记忆更不容易出错,也能推广到其他复合类型~


总结

这是我理想中知识点记录的效果,真的非常满意这种记录结果,清晰透彻,希望以后的文章也可以这样不再啰里啰唆,绕来绕去讲不清楚。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值