<p>const int p是指向常量的指针,const修饰int,禁止通过p修改所指内容;int const p是指针常量,const修饰p本身,禁止修改指针地址;const位置决定编译器拦截赋值的位置。</p>

const int* p 是指向常量的指针,不是“常量指针”这个说法本身就有误导
很多人一看到“常量指针”就默认是 const int* p,但这个词在 C++ 社区和标准文档里其实不严谨——它真正该叫「指向常量的指针」。关键不在名字,而在 const 修饰谁:const int* p 中 const 紧贴 int,说明它限制的是 *p 的值,即“你不能通过 p 改 *p”。p 自己完全可以重新赋值,比如 p = &b。
常见错误现象:
- 编译报错
error: assignment of read-only location '*p'—— 就是误对const int* p解引用后赋值 - 误以为
const int* p只能指向const int变量:其实它可以指向普通int a,只是禁止你用p去改a(a = 100依然合法)
int* const p 才是真正的“指针常量”,const 在 * 右边
int* const p 的 const 紧挨着 p,修饰的是指针变量本身。这意味着 p 的值(也就是它存的地址)从初始化后就不能再变。但它指向的内容完全可写,*p = 42 没问题。
必须注意的硬性约束:
立即学习“C++免费学习笔记(深入)”;
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
-
int* const p必须在定义时初始化,比如int* const p = &a;不初始化会编译失败 - 后续任何试图修改
p地址的操作,如p = &b,都会触发error: assignment of read-only variable 'p' - 这种写法常用于封装类成员:比如某个资源句柄一旦绑定就不该被重定向,就用
FILE* const fp
从右向左读法比记名字更可靠
别纠结“常量指针”还是“指针常量”这种中文命名,直接看声明语法。把声明当成英文句子读,从变量名开始往左解析:
-
const int* p→ “p is a pointer to const int”(p 是一个指向 const int 的指针) -
int* const p→ “p is a const pointer to int”(p 是一个指向 int 的 const 指针) -
const int* const p→ “p is a const pointer to const int”(两者都不可变)
这个读法在函数参数、模板推导、类型别名(using)中同样适用,比如 std::vector<const int const></const> 也能清晰拆解。
const 在 * 左还是右,决定了编译器拦哪一行代码
这是最实际的判断依据:看 const 紧邻的是 * 还是类型名。
-
const在*左边(如const int* p)→ 编译器拦*p = ... -
const在*右边(如int* const p)→ 编译器拦p = ... - 两边都有(
const int* const p)→ 两行都被拦
容易被忽略的是:当指针作为函数参数传入时,void f(const int* p) 和 void f(int* const p) 对调用方几乎没区别(因为形参本身就是局部副本),但前者能接收 const int* 和 int* 实参,后者只影响函数体内能否重绑定 p,实际意义很弱——除非你在写内联汇编或极端性能敏感路径。

















