C++ 中 const 与 constexpr 的辨析
2025-04-02
在 C++ 中,const
和 constexpr
都增强了代码的健壮性和意图表达,但它们关注点不同。const
关注的是运行时不变性(只读),而 constexpr
关注的是编译时确定性(常量表达式)。
const:运行时或编译时的“只读”
const
是我们更熟悉的关键字。它的核心含义是:一旦初始化,变量的值就不能被修改。
不变性 (Immutability)
这是 const
的主要目的。它告诉编译器和其他开发者这个变量不应该被改变。
1 | const int max_users = 100; |
初始化时机
const
变量可以在运行时或编译时初始化。这意味着你可以用一个在编译时未知的值来初始化
const
变量。
1 | int get_runtime_value() { |
const 与指针/引用
const
可以用来修饰指针本身或指针指向的数据(或两者),以及引用。
1 | const int* ptr_to_const; // 指向 const int 的指针 (不能通过 ptr 修改 int) |
constexpr:编译时可求值的“常量表达式”
constexpr
是 C++11
引入的关键字,其核心含义是:这个表达式或函数可以在编译时求值。
编译时求值 (Compile-Time Evaluation)
这是 constexpr
的主要目的。它允许将计算从运行时提前到编译时,可以用于性能优化、模板元编程以及需要编译时常量的地方(如数组大小、模板参数等)。
编译时常量
constexpr
变量必须用常量表达式初始化。常量表达式是指编译器在编译期间就能确定其值的表达式。constexpr
变量隐含const
。它们的值在初始化后也不能被修改。- 它们是真正的编译时常量。
1 | constexpr int compile_time_known = 10; |
函数 (Functions) & 构造函数 (Constructors)
constexpr
函数是指如果用常量表达式作为参数调用,它就能够在编译时产生一个常量表达式结果。
如果用运行时值调用 constexpr
函数,它就像普通函数一样在运行时执行。
C++11 对 constexpr
函数限制较多,C++14
及以后放宽了限制,允许包含更多逻辑(如局部变量、循环、if
语句等),只要满足能在编译时求值的条件即可。
1 | constexpr int square(int n) { |
两者何时使用?
当你需要一个变量在初始化后不被修改,但其初始值可能在运行时才能确定时,使用
const
。
1 | // 运行时确定 |
当你需要一个真正的编译时常量时(例如用于数组大小、模板非类型参数、枚举值、需要保证在编译期就固定的值),或者你想确保某个计算能在编译时完成,使用
constexpr
。
1 | constexpr size_t buffer_size = 1024; |
对于函数,如果你希望它有可能在编译时执行(当输入是编译时常量时),就将其标记为
constexpr
。