const修饰指针时位置决定语义:左为“指向常量的指针”,右为“常量指针”,二者类型不兼容;字符串字面量必须用const char*接收;const成员函数中this为const指针,只能调用const成员函数;mutable是唯一可在const函数中修改的例外。

const 修饰指针时,const 放在 * 左边还是右边,直接决定语义——不是“差不多”,而是编译器完全不同的类型检查。写错位置,轻则函数调用失败,重则逻辑被绕过却无报错。
const int* p 和 int* const p 编译期就不是同一个类型
前者是「指向常量的指针」,后者是「常量指针」。它们在类型系统里互不兼容,不能隐式转换,也不能用于重载区分(因为顶层 cv-qualifier 不参与函数签名)。
-
const int* p:可改p的值(即换地址),不可改*p(即不能写*p = 5) -
int* const p = &x:必须初始化;之后p = &y报错,但*p = 5合法 -
const int* const p = &x:两者都禁止,是最严格的只读访问 - 读法建议从右往左:
int* const p→ “p is a const pointer to int”
字符串字面量强制要求 const char*
像 "hello" 这种字面量,类型是 const char[6],现代 C++(C++11 起)禁止隐式转成 char*。这不是警告,是硬性编译错误。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 错:
char* p = "hello";→ error: cannot convert 'const char*' to 'char*' - 对:
const char* p = "hello"; - 若真要非常量指针(极少见且危险):
char* p = const_cast<char>("hello");</char>,但后续写操作仍是未定义行为(UB) - 安全替代:
char p[] = "hello";(数组初始化,不涉及 const 转换)
const 成员函数里只能调用 const 成员函数
声明为 void foo() const 的函数,this 指针类型是 const MyClass*。这意味着所有非 mutable 成员变量都变成只读,且只能调用其他 const 成员函数。
- 常见报错:
error: passing 'const MyClass' as 'this' argument discards qualifiers - 典型场景:
const std::vector<int>& v</int>只能调用v.size()、v.at(i),不能调用v.push_back(x) -
mutable是唯一例外:它允许在const函数中修改(比如缓存计算结果),但该字段不能影响对象的逻辑状态 - 返回
*this时若写成const MyClass&,链式调用后续将无法接非 const 函数
const 引用参数不是为了“防手抖”,而是契约与生命周期管理
写 void f(const std::string& s),重点不在防止你内部误改 s,而在于告诉调用方:“我不会动你传来的对象”,并让编译器据此优化(如省去隐式拷贝)和延长临时对象生命周期。
- 接受临时对象:
f(std::string("tmp"))合法;而void f(std::string& s)不合法 - 但注意:
const T&延长的是绑定到它的那个临时对象的生命周期,不传递给函数内部创建的新引用 - 更隐蔽的坑:如果
T自身没实现 const 正确性(比如成员函数没加const),哪怕参数是const T&,调用其非 const 成员也会失败 - 基本类型(
int、double)传const int&没实际收益,编译器通常忽略;大对象才值得
真正难的不是记住哪边是“指针常量”,而是写出 const 正确的类——每个访问器是否标记 const,哪些字段该加 mutable,返回引用时要不要 const,这些组合起来才构成完整的只读契约。漏掉一个点,整个 const 系统就形同虚设。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










