C++里的const和constexpr有什么区别?(编译时常量与运行时常量)
技术百科
穿越時空
发布时间:2026-01-22
浏览: 次 const仅表示不可修改,不保证编译期常量;constexpr才强制编译期可求值,用于模板参数、数组维度等需常量表达式的场景。
const 不一定代表编译期常量
const 只表示“不可修改”,但它的值可能在运行时才确定。比如:const int x = rand(); 是合法的(只要 x 在作用域内不被修改),但 x 显然不是编译时常量,不能用在需要常量表达式的地方。
常见错误现象:把 const int N = 10; 当成能当数组长度用的“真常量”,结果在 C++98/03 中可能失败(取决于是否为字面量初始化);C++11 起放宽了部分限制,但仍要看初始化方式。
- 若用字面量或 constexpr 表达式初始化(如
const int a = 42;或const int b = foo();,且foo()是constexpr),则a、b是“字面类型 + 常量初始化”,可作常量表达式(但需注意上下文) - 若用运行时值初始化(如
int n = 5; const int c = n;),c就只是只读变量,不能用于模板非类型参数、switchcase、数组维度等 - 对指针/引用,
const int* p和int const* p等价,但int* const是指针本身 const —— 这和
p
constexpr无关,纯属const修饰位置问题
constexpr 强制要求编译期可求值
constexpr 是更严格的契约:它要求变量或函数必须能在编译期计算出结果,且只能依赖编译期已知的值。一旦违反(比如调用了非 constexpr 函数、用了 new、有未定义行为),编译器直接报错。
使用场景包括:模板参数、std::array 大小、if constexpr 分支、静态断言等所有需要“常量表达式”的地方。
-
constexpr变量隐含const,但const变量不隐含constexpr - C++14 起,
constexpr函数允许更宽松的函数体(如局部变量、循环、条件分支),只要所有可能执行路径都满足编译期可求值 - 注意返回类型和参数类型必须是字面类型(literal type),例如
std::string不是字面类型,所以constexpr std::string s = "hi";非法(C++20 前)
看一个典型对比示例
int global = 42;constexpr int f1() { return 100; } const int f2() { return 200; } // ❌ 错误:const 不能修饰函数(这是语法错误,仅作对比示意)
int main() { const int a = 5; // OK,但 a 不一定是编译时常量 constexpr int b = a; // ❌ 错误:a 不是 constexpr(即使值是 5,但未声明为 constexpr) constexpr int c = 5; // ✅ 正确 constexpr int d = f1(); // ✅ 正确:f1 是 constexpr 函数 // constexpr int e = global; // ❌ 错误:global 是运行时变量 // int arr[a]; // C++98/03 中非法;C++11 起若 a 是“核心常量表达式”才允许(此处 a 不是 constexpr,不一定行) int arr[c]; // ✅ 安全:c 是 constexpr
return 0;}
容易被忽略的细节:const 成员函数 vs constexpr 成员函数
类中声明
void foo() const表示不修改对象状态;而constexpr void bar() const不仅要求bar是 const 成员函数,还要求其整个执行逻辑可在编译期完成,且所在类必须是字面类型(有平凡析构、所有非静态成员都是字面类型等)。这意味着:即使一个
const成员函数逻辑简单,只要它调用了非constexpr的其他函数,或者访问了mutable成员(哪怕没改),就不能标为constexpr。
-
constexpr构造函数必须初始化所有成员,且每个初始化器都必须是常量表达式 - 从 C++20 开始,
constexpr支持更多运行时操作(如动态内存分配),但实际编译器支持程度不一,不能默认依赖 - 调试时如果遇到 “not a constant expression” 错误,优先检查是否混用了非
constexpr变量、函数或类型,而不是怀疑语法
# ai
# 都是
# 这是
# 能在
# 用了
# 要看
# 可在
# 就不能
# 不被
# 循环
# 对象
# c++
# String
# if
# int
# void
# 区别
# 指针
# 构造函数
# 报错
# 成员函数
# 作用域
# switch
# const
# 局部变量
# 常量
# Array
# 求值
# mutable
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- 如何解决Windows字体显示模糊的问题?(Cle
- Golang如何测试HTTP中间件_Golang
- 如何解决同一段404代码在不同主机上表现不一致的问
- PHP的Workerman对架构扩展有啥帮助_应用
- Win11怎么设置快速访问_Windows11文件
- Win11怎么关闭小组件_Win11禁用任务栏天气
- c++的STL算法库find怎么用 在容器中查找指
- php后缀怎么变mp4能播放_让php伪装mp4正
- Python函数缓存机制_lru_cache解析【
- 如何在 Go 后端安全获取并验证前端存储的 JWT
- Windows 11如何开启文件夹加密(EFS)_
- c++ std::atomic如何保证原子性 c+
- WindowsUSB驱动安装异常怎么办_USB驱动
- Win11文件夹预览图不显示怎么办_Win11缩略
- 如何使用Golang包导出规则_控制函数和变量可见
- php中常量能用::访问吗_类常量与作用域操作符使
- Win11怎么清理C盘下载文件夹_Win11清理下
- 如何使用Golang recover捕获panic
- 如何使用Golang管理模块版本_Golanggo
- 如何在 Django 中修改用户密码后保持会话不丢
- Python脚本参数接收_sys与argparse
- Win11如何设置文件关联 Win11修改特定文件
- c++如何利用doxygen生成开发文档_c++
- Win10路由器怎么隐藏ssid Win10隐藏w
- Python函数参数高级用法_默认值与可变参数解析
- Win11任务栏颜色怎么改_Win11自定义任务栏
- Win11任务栏天气怎么关闭 Win11隐藏天气小
- 如何用正则与预处理高效拦截带干扰符的恶意域名
- 如何使用Golang读取日志文件_Golang b
- mac怎么退出id_MAC退出iCloud账号与A
- Windows电脑如何截屏?(四种快捷方法)
- Python装饰器设计思路_功能增强机制说明【指导
- Win11怎么开启HDR模式_Windows 11
- Win11如何设置系统声音_Win11系统声音调整
- Win11怎么关闭通知消息_屏蔽Windows 1
- MAC如何启用访达侧边栏显示_MAC Finder
- Python配置文件操作教程_JSONINIYAM
- php怎么下载安装后无法解析php文件_服务器配置
- 如何在 Go 开发中正确处理本地包导入与远程模块路
- Windows10如何删除恢复分区_Win10 D
- Win11如何设置ipv6 Win11开启IPv6
- Windows10电脑怎么连接蓝牙设备_Win10
- Win10怎样卸载TeamViewer_Win10
- Windows怎样关闭锁屏广告_Windows关闭
- Python多进程教程_multiprocessi
- php下载安装包太大怎么下载_分卷压缩下载方法【教
- 如何将文本文件中的竖排字符串转换为横排字符串
- 如何自定义Windows终端的默认配置文件?(Po
- Win11怎么检查TPM2.0模块_Windows
- Windows如何设置登录时的欢迎屏幕背景?(锁屏


QQ客服