const成员变量必须在构造函数初始化列表中初始化,不可在函数体内赋值;static const整型可类内初始化,非整型需类外定义;c++17起推荐用inline static constexpr替代,支持任意类型且避免odr问题。

const 成员变量必须在构造函数初始化列表里赋值
类内声明的 const 成员变量不能在构造函数体里用等号赋值,否则编译失败。因为 const 对象一旦生成就不能再写入,而构造函数体执行时对象已经完成内存分配,此时再“赋值”违反常量语义。
常见错误现象:error: uninitialized const member 或 error: assignment of read-only member
- 必须写在构造函数初始化列表中,例如:
MyClass() : kValue(42) {} - 不能写成:
MyClass() { kValue = 42; }(非法) - 如果类有多个构造函数,每个都得显式初始化该
const成员 - 初始化表达式可以是字面量、
constexpr变量、或调用constexpr函数,但不能是运行时计算结果(除非是constexpr构造函数)
static const 整型成员可直接在类内定义初值
对于整型(int、long、enum 等)的 static const 成员,C++11 起允许在类内用字面量直接初始化,无需在 .cpp 中重复定义。
使用场景:定义类级别的常量配置,比如最大连接数、协议版本号。
- 合法写法:
static const int MAX_RETRY = 3; - 非整型(如
static const std::string)仍需在类外定义,否则链接时报undefined reference - 即使类内初始化了,若取其地址(
&MyClass::MAX_RETRY),仍需在 .cpp 中提供一次定义(空定义即可:const int MyClass::MAX_RETRY;)
C++17 起优先用 inline static 替代 static const
inline static 解决了 static const 的链接和定义歧义问题,且支持任意类型,语义更清晰。
性能与兼容性影响:所有标准 C++17 及以上编译器都支持;比传统 static const 更少出错,尤其对非整型常量。
- 推荐写法:
inline static const double PI = 3.1415926;或inline static const std::string NAME = "test"; - 不用再管头文件多次包含导致的重定义问题
- 无需在 .cpp 中补定义,也无需担心 ODR 违规
- 注意:
inline static成员仍属于类作用域,不是每个对象一份,而是整个程序一份
constexpr 成员变量需要满足编译期可求值
constexpr 比 const 要求更高——它要求值在编译期就能确定,且类型必须是字面量类型(literal type)。
容易踩的坑:把运行时才能拿到的值(比如文件读取结果、用户输入)误标为 constexpr,会直接编译失败。
- 合法示例:
constexpr int kSize = sizeof(int) * 8; - 非法示例:
constexpr int x = rand();(rand()非 constexpr 函数) - 类内
constexpr静态成员也建议用inline static constexpr(C++17+),避免老式定义方式的繁琐 - 非静态
constexpr成员变量几乎无意义,因为每个对象实例的值可能不同,无法保证编译期确定,所以实践中基本只用于static场景
实际项目里最容易忽略的是:把 const 成员当成普通变量去“赋值”,或者以为 static const std::string 能像整型一样类内初始化。这两个点一错,轻则编译不过,重则链接失败且报错信息不直观。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











