<p>const int 和 int const 完全等价,均表示顶层 const 修饰的 int;但加入 后,const 位置决定修饰对象:const int 与 int const 等价(指针可变、所指不可变),而 int const 表示指针本身不可变。</p>

const int 和 int const 完全等价,编译器不区分
它们声明的是同一种类型:一个顶层 const 修饰的 int。无论写成 const int a = 42; 还是 int const b = 42;,a 和 b 都是只读整数,不能赋值修改。
原因在于 C++ 声明语法的“从右向左”解读规则:int const 读作“const 的 int”,const int 同样读作“const 的 int”。const 左边没类型,就修饰右边的 int,结果一致。
- 两者在模板推导中都被视为
int(top-level const 被忽略) - 用
decltype检查类型,结果都是const int - 函数参数声明中可混用,如
void f(const int x)和void f(int const x)是同一签名
真正关键的分水岭在 * 出现之后
一旦加入指针符号 *,const 的位置立刻决定它修饰谁——这正是容易混淆、也必须厘清的地方。
const int* 和 int const* 还是等价的,都表示“指向常量 int 的指针”;但 int* const 就完全不同了,它表示“常量指针,指向 int”。
立即学习“C++免费学习笔记(深入)”;
-
const int* p;→p可改,*p不可改 -
int* const q = &x;→q必须初始化且不可改,*q可改 -
const int* const r = &x;→r和*r都不可改
模板传参时 top-level const 会被静默丢弃
这是实战中最容易踩坑的点:当你把 const int* 或 int const* 传给模板函数,T 推导出的不是带 const 的类型,而是裸 int*。
例如:
template<typename T> void f(T param);<br>const int* ptr = &x;<br>f(ptr); // T 是 int*, 不是 const int*
- 若需保留 const,必须用引用:
template<typename T> void f(const T& param) - 或显式指定模板实参:
f<const int*>(ptr) - 指针常量
int* const同样适用该规则:传值时const修饰指针本身也被忽略
建议写法:统一把 const 放左边,但理解比格式更重要
社区主流习惯是写 const int* 而非 int const*,但这只是风格;真正影响行为的是 const 相对于 * 的位置。
- 遇到复杂声明(比如
int (*(*p)[10])(int)),别硬读,用using拆解 - 写
const int* p时,心里默念:“p 是指针,指向 const int” - 写
int* const p时,默念:“p 是 const 指针,指向 int” - 所有歧义都来自对“
const修饰谁”的误判,而不是const int和int const的差异
复杂声明里 const 的层级和位置稍一错位,语义就彻底翻转,靠死记硬背不如建立“从右向左 + const 紧贴被修饰物”的直觉。


















