const修饰紧挨的标识符:const int p中const修饰int(p不可改),int const p中const修饰p(p地址不可改),const int const p中const同时修饰int和p(二者均不可改)。

const 在指针声明中到底修饰谁?
看 const 紧挨着谁,就修饰谁——这是唯一可靠判断依据。不是看“左边还是右边”,因为 const 可以前置或后置,而 C++ 允许两种写法:const int* p 和 int const* p 完全等价。真正起作用的是它离哪个标识符最近。
常见错误是凭语感记“指针常量”“常量指针”,结果一换顺序就懵。比如 int* const p = &x; 中,const 紧挨 p,所以 p 本身不可变(地址不能改),但 *p 可改;而 const int* p 中,const 紧挨 int,所以 *p 不可改(值不能改),但 p 可以指向别处。
三种典型写法与对应行为
实际开发中最容易混淆的是这三种组合,每种都对应明确的约束:
-
const int* p或int const* p:指向常量的指针。可改p(重定向),不可改*p(不能通过它修改所指对象) -
int* const p = &x;:常量指针。不可改p(初始化后地址固定),可改*p(能修改所指对象的值) -
const int* const p = &x;:指针本身和它指向的内容都不可变。既不能改p,也不能改*p
注意:int const* p 是合法且常用写法,尤其在模板或 typedef 场景下更清晰,别误以为只有 const int* 才标准。
立即学习“C++免费学习笔记(深入)”;
为什么 int* const p 必须初始化?
因为 const 修饰的是指针变量 p 本身,意味着它的值(即存储的地址)从诞生起就不能再被赋值。C++ 要求所有 const 对象必须在定义时初始化。
以下写法非法:
int x = 10; int* const p; // ❌ 编译错误:未初始化 const 指针 p = &x; // ❌ 即使补上这句也不行,p 已是未定义行为
正确写法只有一种:
int x = 10; int* const p = &x; // ✅ 必须在定义时绑定地址
函数参数中用 const T* 还是 T* const?
绝大多数情况该用 const T*(即指向常量的指针),目的是保证函数内部不修改调用者传入的数据。例如:
void print(const char* s) { /* 只读 s */ }T* const 在参数中几乎无意义——函数内本就不能改变形参指针的地址(它只是栈上一份拷贝),加 const 纯属多余,编译器通常会忽略或警告。
真正需要 T* const 的场景极少,常见于类成员指针(如指向某个固定资源的句柄),且必须在构造函数初始化列表中赋值。
容易被忽略的一点:当使用 const 修饰指针所指内容时,如果原对象本身不是 const,你仍可通过其他非 const 指针修改它——const 只约束当前这个指针的访问权限,不改变对象本质。










