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 内容和指针都不可变 不可修改 不可修改
相关推荐
网域小星球4 小时前
C 语言从 0 入门(十二)|指针与数组:数组名本质、指针遍历数组
c语言·算法·指针·数组·指针遍历数组
Tairitsu_H4 小时前
C语言:排序(一)
c语言·数据结构·排序
tod1134 小时前
深入解析ext2文件系统架构
linux·服务器·c++·文件系统·ext
不想写代码的星星4 小时前
C++ 类型萃取:重生之我在幼儿园修炼类型学
c++
比昨天多敲两行4 小时前
C++11新特性
开发语言·c++
xiaoye-duck4 小时前
【C++:C++11】核心特性实战:详解C++11列表初始化、右值引用与移动语义
开发语言·c++·c++11
睡一觉就好了。4 小时前
二叉搜索树
c++
希望永不加班4 小时前
SpringBoot 事件机制:ApplicationEvent 与监听器
java·开发语言·spring boot·后端·spring
whitelbwwww4 小时前
C++进阶--类和模板
c++