C/C++ const:修饰变量和指针的区别(和引用底层关系)

在C++学习中,const 是一个非常基础但极易混淆的关键字,尤其是当它和指针结合时,很多新手都会被 const int *pint *const p 这类写法搞懵。

其实不用慌,核心就一个原则:const 离谁近,谁就不能改

一、先搞懂基础:const 修饰普通变量

这是最简单、最常用的用法,一句话就能说透:const 修饰普通变量,就是给变量"上锁",让它变成只读的,不能再修改

代码示例:

cpp 复制代码
const int a = 10; // 用const修饰变量a
a = 20; // 报错!不能修改const修饰的变量

核心特点:变量本身的值不可变,一旦初始化,就不能再赋值。这是 const 最基础的用法,没什么难度,重点在后面和指针的结合。

二、重点难点:const 修饰指针(3种情况)

const 和指针结合,之所以容易乱,是因为 const 可以修饰"指针本身",也可以修饰"指针指向的内容"。记住一个口诀,瞬间理清:

cpp 复制代码
const 在 * 左边 → 指针指向的内容不能改
const 在 * 右边 → 指针本身不能改
两边都有 → 内容和指针都不能改

1. const 在 * 左边:指向的内容不能改(此时const 修饰*p,也就是地址里存的值不能改)

写法有两种,效果完全一样,随便写哪种都可以:

cpp 复制代码
const int *p; // 写法1
int const *p; // 写法2

核心规则:不能通过指针 p 修改它指向的内容,但指针 p 本身可以指向别的变量

代码示例:

cpp 复制代码
int a = 10, b = 20;
const int *p = &a; // 指针p指向a

*p = 100; // 报错!不能修改指向的内容
p = &b;   // 正确!指针可以换指向

2. const 在 * 右边:指针本身不能改(此时const修饰p,也就是地址不能改)

写法只有一种,注意 const 的位置

cpp 复制代码
int *const p;

指针 p 不能再指向别的变量,但可以修改它指向的内容:

cpp 复制代码
int a = 10, b = 20;
int *const p = &a; // 指针p固定指向a(初始化时必须赋值,否则报错)

*p = 100; // 正确!可以修改指向的内容(电视可以调音量)
p = &b;   // 报错!指针不能换指向(遥控器不能换台)

注意:这种写法,指针 p 必须在初始化时就指定指向的变量,不能先定义再赋值(比如 int *const p; 单独写会报错)

2.1 引用的底层实现 = const指针(int *const ref

:即"指针本身不能改指向",这也是引用不能改绑的原因;

我们写一句简单的引用代码:

cpp 复制代码
int a = 10;
int &ref = a; // 引用ref绑定变量a

这段代码,编译器在底层会悄悄翻译成类似这样的指针操作(注意:这是底层实现,我们写代码不能这么写):

cpp 复制代码
int a = 10;
int *const ref = &a; // 底层用const指针实现引用

这就解释了两个关键问题:

  1. 为什么引用必须初始化? → 因为const指针(int *const ref)必须在初始化时指定指向,引用底层是const指针,所以语法上要求引用必须绑定变量才能定义,不能先定义再赋值(比如int &ref;会报错)。

  2. 为什么引用不能改绑? → 因为底层的const指针,本身不能改指向(ref = &b会报错),所以引用一旦绑定某个变量,就不能再绑定其他变量(比如ref = b是给a赋值,不是改绑)。

3. 两边都有 const:内容和指针都不能改

cpp 复制代码
const int *const p;

核心规则:既不能修改指向的内容,也不能修改指针本身的指向,相当于"双重锁定"。

cpp 复制代码
int a = 10, b = 20;
const int *const p = &a;

*p = 100; // 报错!不能改内容
p = &b;   // 报错!不能改指向

三、一张表彻底记牢(建议收藏)

为了方便大家快速查阅,整理了所有情况的对比,一目了然:

写法 通俗含义 指向的内容(*p) 指针本身(p)
int *p 普通指针 可修改 可修改
const int *p / int const *p 指向常量的指针 不可修改 可修改
int *const p 指针本身是常量 可修改 不可修改
const int *const p 内容和指针都不可变 不可修改 不可修改
相关推荐
葡萄城技术团队12 小时前
InfluxDB 2\.x 深度解析:核心架构、Flux 函数与制造业落地指南(三)
java·开发语言·架构
counting money12 小时前
Java IO流详解:从InputStream到文件操作实战
java·开发语言·python
wuyk55513 小时前
98.C语言易混难点:字符数组与字符串指针的底层差异
c语言·开发语言·c++·stm32·嵌入式硬件·算法
峥无13 小时前
从0到1手撕红黑树:封装实现 my_map 与 my_set(SGI-STL 源码级深度解析)
开发语言·c++·笔记·算法·stl
波特率11520013 小时前
C++新特性---属性说明符与标准属性
开发语言·c++
程序员小八77713 小时前
上海百度B端java后端日常实习一面
java·开发语言
wp123_113 小时前
IPX8 防水 Type‑C连接器:安费诺 124018792112A 与 TONEVEE TY48087‑24A 技术梳理
c语言·开发语言
不会代码的小猴13 小时前
3. 控件学习1
开发语言·c++·笔记·qt·算法
fangzhanpeng16814 小时前
(前端)2.js变量作用域样例
开发语言·前端·javascript
mqiqe16 小时前
线程调度与 Schedulers:Project Reactor 并发模型的核心引擎
java·开发语言·网络