类内整型常量必须用 static constexpr 初始化;字符串常量c++17起推荐 static inline const std::string 或 static constexpr const char*;模板中依赖类型的常量需 static constexpr 且表达式须对所有实例合法;头文件中应避免非 constexpr 静态常量重复定义。

类内定义整型常量用 static constexpr
直接在类声明里初始化整型(int、size_t、bool 等字面量类型)常量,必须加 static 和 constexpr。只写 const 会编译失败(C++11 起),因为非静态 const 成员不能在类内赋初值。
-
static表示该常量属于类而非对象实例,避免每个对象都存一份 -
constexpr表示它在编译期可求值,能用于需要常量表达式的地方(比如数组长度、模板参数) - 不加
static:报错error: invalid use of non-static data member - 只加
const不加constexpr:C++17 前可能允许但不可用于模板实参;C++17 后仍推荐用constexpr
示例:
struct Config {
static constexpr int MAX_RETRY = 3;
static constexpr size_t BUFFER_SIZE = 1024;
};
类内定义字符串常量用 static inline const(C++17)或 static constexpr(仅字面量)
字符串字面量("hello")本身是 const char[N] 类型,不能直接用 constexpr 绑定到 std::string——因为 std::string 构造函数不是 constexpr(直到 C++20 才部分支持)。所以常见做法分两类:
- 若只需只读 C 风格字符串:
static constexpr const char* NAME = "app"; - 若需
std::string对象且 C++17+:static inline const std::string VERSION = "1.2.0";(inline解决 ODR 违规,避免多定义错误) - 旧标准(C++11/14)中,
std::string必须在类外定义,否则链接时报undefined reference
错误示范(C++17 前):
struct App {
static const std::string NAME = "myapp"; // ❌ 编译通过但链接失败
};
模板类中常量定义要加 static constexpr 并注意依赖类型
模板类里的常量如果依赖模板参数(比如 T::value 或 sizeof(T)),必须用 static constexpr,且初始化表达式必须对所有实例化类型都合法。
- 若表达式在某次实例化时无效(如对
void取sizeof),编译器会 SFINAE 掉该特化,但不会静默忽略——得靠requires或std::enable_if约束 - 避免在常量定义中调用非
constexpr函数(哪怕函数名看起来“安全”,如std::abs在 C++20 前多数实现非 constexpr) - 模板内使用
inline没必要:模板本身已隐式 inline,重复定义不触发 ODR 错误
示例(安全):
template<typename t>
struct Traits {
static constexpr size_t alignment = alignof(T);
static constexpr bool is_fundamental = std::is_fundamental_v<t>;
};</t></typename>
头文件里定义常量要防重复定义(尤其非 constexpr)
如果用了 static const(非 constexpr)或 static inline const 以外的方式,在头文件中定义类内常量,多个源文件包含该头文件时可能违反 ODR(One Definition Rule)。
-
static constexpr是安全的:它本质是编译期符号,不占数据段,无链接实体 -
static inline const(C++17)也是安全的:inline明确允许在多个 TU 中定义 - 老写法
static const int X = 42;:C++17 前必须在 .cpp 中定义一次(即使有初始化),否则链接失败 - 宏
#define看似简单,但无类型、不进调试器、无法取地址,应避免
容易被忽略的是:即使你写了 static constexpr,如果类型自定义且构造函数没标 constexpr,依然编译不过——常量性会逐层传导。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











