const紧邻谁就修饰谁:const int p表示p不可改而p可改;int const p表示p不可改而p可改;const int* const p二者均不可改。

const 放在 * 左边还是右边?关键看修饰谁
“指向常量的指针”和“常量指针”是两回事,语法差异只在 const 相对于 * 的位置,但语义完全不同。很多人一上来就记混,结果编译报错还找不到原因。
记住一个口诀:const 紧邻谁,就修饰谁。
-
const int* p;或int const* p;:指针p指向的内容不可改(即*p是 const),但p本身可重新赋值指向别处 -
int* const p = &x;:指针p本身不可改(地址固定),但*p可修改 -
const int* const p = &x;:指针和它指向的内容都不可改
为什么 int const* 和 const int* 等价?
因为 const 修饰的是紧邻的类型部分,在 int const* 中,const 紧挨着 int,所以是“常量 int 类型的指针”;而 const int* 里 const 也在 int 左侧,效果一致。C++ 标准允许这两种写法,但前者更体现“const 修饰类型”的本质,也更容易扩展到复杂声明(比如 int const* const)。
反例:int* const const p; 是非法的——重复 const 修饰同一对象,编译器会报 error: duplicate 'const'。
立即学习“C++免费学习笔记(深入)”;
常见错误:把 const int* 当成“不能改指针”
这是新手最常踩的坑。写成 const int* p = &x; 后,误以为 p = &y; 会报错,其实不会——报错的是 *p = 10;。
典型错误现象:
- 想保护数据不被意外修改,却用了
int* const p,结果发现函数传参时无法接收不同地址,反而限制了灵活性 - 函数参数写成
void f(int* const p),本意是防改数据,实际只是防改指针,起不到保护作用 - 返回局部变量地址时加
const int*,误以为能延长生命周期——const 不影响对象生存期,该 dangling 还是 dangling
什么时候必须用 const 修饰指针所指内容?
主要出现在接口契约明确、数据只读的场景,尤其是函数参数和容器迭代器。
例如:
void print(const char* str) { /* str 内容不可改 */ }这样调用 print("hello") 才合法,因为字符串字面量类型是 const char[6],只能绑定到 const char*,不能绑定到 char*(C++11 起禁止隐式降级)。
再比如 std::vector 本质就是 const int* 的封装,解引用得到 const int&,防止误改容器元素。
真正容易被忽略的是:const 修饰的不只是“能不能写”,它还参与类型匹配、重载决议和模板推导——少写一个 const,有时连函数都进不去。










