C++ const 与 constexpr:真正的区别是什么?
一眼看都是定义常量。
为什么这很重要
现代 C++ 鼓励编写不可变、高效且表达力强的代码。两个关键字—const 和 constexpr—是这一理念的核心。它们看起来很相似,但理解它们的不同语义,对于正确利用编译期与运行期行为至关重要。
高层次对比
| 特性 | const |
constexpr |
|---|---|---|
| 编译期常量? | 可能 | 一定(否则编译报错) |
| 支持运行期? | 支持 | 支持(在需要时运行期求值) |
| 用于数组/模板参数? | 仅当确实是常量 | 保证可用 |
| 允许函数? | 仅限成员函数限定符 | 支持完整函数且可在编译期求值 |
1 声明不可变数据
const:构造后不可变
const int runtimeConst = std::rand(); // 是 const,但不是编译期常量
当你只想禁止变量被修改,而不在意值是在编译期还是运行期确定的,const 就足够了。
constexpr:必须在编译期已知
constexpr int arraySize = 10;
int arr[arraySize]; // 始终合法
如果值需要参与要求编译期常量的上下文(如数组大小、模板参数、switch 标签等),你必须使用 constexpr。
2 函数与方法
const 成员函数
class Widget {
public:
int value() const {/*…*/} // 保证不会修改 this 对象
};
它保护对象状态,但不提供编译期求值能力。
constexpr 函数
constexpr int square(int n) { return n * n; }
static_assert(square(4) == 16, "编译期计算");
constexpr 函数在参数是常量表达式时可以在编译期执行,也可以在运行期使用。
3 常见陷阱
// 1. 编译通过:runtimeConst 只是 const
const int runtimeConst = std::rand();
// 2. 编译失败:std::rand() 不是 constexpr
constexpr int fails = std::rand();
记住:每个 constexpr 变量本质上都是 const,但并非所有 const 都是常量表达式。
4 如何选择
- 需要强制编译期计算?使用
constexpr - 需要不可变性但值可能在运行期确定?使用
const - 不确定时偏向使用
constexpr,编译器会提示你是否不合法
5 总结片段
constexpr int ctVal = 42; // 编译期常量
const int rtVal = std::rand(); // 运行期确定,但不可变
正确地选择 const 和 constexpr 能让你的 C++ 代码更安全、更高效、更具表达力。默认使用 constexpr,当且仅当你明确知道值只能在运行期获取时才使用 const。
C/C++编程
- 理解C++中的std::transform_reduce及示例
- 使用原子 TAS 指令实现自旋锁
- C++中检测编译时与运行时: if consteval 与 std::is_constant_evaluated()
- C++ 转发引用: 完美转发的关键
- 理解 C++ 中的 dynamic_cast: 安全的向下转型与向上转型
- C与C++: restrict关键字及其在编译器优化中的作用
- C++的左值/lvalue, 右值/rvalue和右值引用/rvalue references
- C++中的assert和static_assert的区别
- C++: auto_ptr智能指针被弃用
- C++中的consteval是什么? 它与const和constexpr有何不同?
- C++ 教程: 用std::move来移动所有权
- C++中的 const和constexpr 比较
- 简易教程: C++的智能指针
- C++ 编程练习题: 如何合并两个二叉树?
- C++ 编程练习题 - 找出第三大的数
- C++ 编程练习题 - 最多连续的 1
- C++ 编程练习题 - 左子树叶节点之和 (深度优先+广度优先+递归)
- C++ 编程练习题 - 最多水容器 (递归)
- C++的异步编程: std::future, std::async 和 std::promise
- C编程练习题: 翻转整数位
- C++编程练习题: 找出字符串的所有大小小组合
- C/C++ 中的内存管理器(堆与栈)
- C++编程练习题: 对两单向链表求和
强烈推荐
- 英国代购-畅购英伦
- TopCashBack 返现 (英国购物必备, 积少成多, 我2年来一共得了3000多英镑)
- Quidco 返现 (也是很不错的英国返现网站, 返现率高)
- 注册就送10美元, 免费使用2个月的 DigitalOcean 云主机(性价比超高, 每月只需5美元)
- 注册就送10美元, 免费使用4个月的 Vultr 云主机(性价比超高, 每月只需2.5美元)
- 注册就送10美元, 免费使用2个月的 阿里 云主机(性价比超高, 每月只需4.5美元)
- 注册就送20美元, 免费使用4个月的 Linode 云主机(性价比超高, 每月只需5美元) (折扣码: PodCastInit2022)
- PlusNet 英国光纤(超快, 超划算! 用户名 doctorlai)
- 刷了美国运通信用卡一年得到的积分 换了 485英镑
- 注册就送50英镑 – 英国最便宜最划算的电气提供商
- 能把比特币莱特币变现的银行卡! 不需要手续费就可以把虚拟货币法币兑换
微信公众号: 小赖子的英国生活和资讯 JustYYUK