【C++】现代C++的constexpr特性

发布时间:2026/10/26 1:25:53

【C++】现代C++的constexpr特性 文章目录一、从C11引入1. 常量表达式和constexpr关键字的概念2. constexpr修饰函数二、constexpr在C14中的进化三、constexpr在C17中的进化四、constexpr在C20中的进化五、C20的consteval和constinit一、从C11引入1. 常量表达式和constexpr关键字的概念现代C从C11开始引入了常量表达式和constexpr关键字的概念并且在之后的C标准中不断更新常量表达式是指值不会改变并且在编译过程中就能得到计算结果的表达式。用字面量、常量表达式初始化的const对象都是常量表达式。但是用变量初始化的const对象不是常量表达式。constinta1;//a是常量表达式constintba1;//b是常量表达式intc1;//c不是常量表达式constintdc;//d不是常量表达式因为可能有代码影响c的值编译时期无法确定c的值由于常量表达式的值在编译时期就能确定编译器在这里就能进行优化在使用常量表达式的地方直接进行替换值通过汇编语言我们能看出区别常量表达式的最大优点就是能将一些计算从运行时转移到编译时提升程序运行时的性能。C11引入了一个关键字constexpr用于指定常量表达式它允许在编译时计算表达式的值。constexpr可以修饰变量但修饰的变量一定要是常量表达式且必须用常量或常量表达式进行初始化否则会报错constexpr也可以修饰指针但修饰的是指针本身也是就顶层const。const可以分为顶层const、底层const。本身被const修饰叫做顶层const、指向的对象被const修饰叫做底层const。大多数普通对象被const修饰时都是顶层const指针被const修饰时*左边的const叫做底层const*右边的const叫做顶层constconst修饰引用时是底层const2. constexpr修饰函数constexpr可以修饰函数constexpr函数默认都是inline的函数的计算会由编译器在编译时期执行。但是一个函数的逻辑可比表达式的逻辑复杂多了这对于编译器的要求就更加严格因此在C11的标准中对constexpr修饰的函数要求也十分严格这个函数的参数和返回值必须都是字面类型目前可以理解为包括整型、浮点型、指针、引用等函数体中只能包含一条语句且是return语句函数体中不能定义局部变量不能有循环语句、条件语句函数必须有返回值返回值必须是常量表达式。函数如果有参数必须传常量或常量表达式不这样传参要用普通变量接收函数结果此时这个函数还是普通函数的运行执行constexpr函数的返回结果必须用一个常量表达式进行接收才能触发编译器的优化。否则这个函数还是像普通函数一样在运行调用时才会计算constexprintfunc1(){return1;}constexprintfunc2(intx){returnx10;}constexprintfunc3(intn){returnn1?1:n*func3(n-1);}intmain(){constexprintafunc1();constexprintbfunc2(10);constexprintcfunc3(5);coutaendl;coutbendl;coutcendl;return0;}通过汇编语句观察确实在编译时期就计算出了a、b、c的结果在cout语句中直接进行了值替换constexpr还能修饰其他函数constexpr修饰构造函数一个类的构造函数被constexpr修饰了才能定义constexpr修饰的类对象。要求该类的所有成员变量必须是字面类型constexpr构造函数必须在初始化列表初始化所有成员变量必须用常量表达式初始化成员变量函数体必须为空该类的析构函数不能做任何实际清理工作constexpr修饰成员函数这个函数自动成为const成员函数参数列表()后要加上const函数内不能修改成员变量constexpr成员函数不能是虚函数其他要求跟普通函数一样constexpr修饰函数模板如果constexpr修饰的函数模板的实例化结果不符合constexpr普通函数的要求则constexpr会自动忽略这个函数就相当于一个普通函数能看出来C11对于constexpr修饰函数还是相当相当严格的但这些规定会在后面的C标准中逐步放开时代还是在进步的~二、constexpr在C14中的进化C14中大幅放宽了对constexpr函数的限制使其语法和功能更接近普通函数允许了constexpr函数内部声明和初始化局部变量支持函数内的if语句、for/while语句、switch语句等函数内可以有多条return语句函数的返回类型可以是void、自定义类型、STL的std::array容器、等更多复合类型实验时要确保编译器支持的是C14标准constexprintfunc(intn){if(n1||n2){returnn;}intret1;//允许局部变量for(inti2;in;i){ret*i;}returnret;//允许多条return语句}intmain(){constexprintafunc(5);coutaendl;return0;}三、constexpr在C17中的进化C17进一步对constexpr扩展使其能力大幅提升进一步模糊了编译时和运行时的界限。其中constexpr可以修饰lambda表达式了要求lambda表达式的捕获必须是常量表达式函数体满足constexpr函数的要求同样实验时保证编译器是C17标准的intmain(){constexprinta10;constexprautofunc[a](intx)constexpr{returnx*a;};constexprintbfunc(5);coutbendl;return0;}四、constexpr在C20中的进化C20是C的最重要的更新之一也同样对constexpr特性进行了革命使编译器的计算能力得到前所未有的提升使其成为现代C元编程和性能优化的核心工具主要更新了以下内容支持了在编译期动态内存分配C20支持constexpr函数中使用动态内存分配new/delete但所分配的内存必须在编译器被释放。这一用法使得STL库的其他容器的编译期实现成为“可能”但C20还无法在constexpr函数内真正使用vector、string等容器涉及内存的操作继续期待未来的更新吧。支持了constexpr函数内的try-catch语句但是实际不能真正抛出异常。这里主要用于模板约束和编译期的错误检测异常必须在编译期捕获和处理不能传播到运行时期。支持了constexpr可变mutable类成员变量原来的constexpr成员函数中不能修改成员变量但C20后在定义成员变量时加上mutable关键字这个成员变量就能在constexpr成员函数中被修改了。支持了constexpr虚函数C20后开始支持虚函数定义为constexpr函数也就是支持了编译器的多态调用。C23是目前最新的C标准但编译器支持仍在路上主要因为标准本身的复杂性、厂商对稳定性的优先考量以及实现策略的差异。让我们期待C的未来无限发展可能吧五、C20的consteval和constinitconstexpr的核心本质是允许在编译器进行计算。但如果上下文要求它在运行时计算constexpr也可以像一个普通函数一样运行。为了杜绝这种不确定性C20引入了consteval这个关键字他比constexpr更严格。consteval修饰的函数必须在编译时被调用和求值如果一个consteval函数不能在编译时被调用和求值那么程序就会编译报错。同时C20另一个关键字constinit用于修饰具有静态存储期或线程存储期的变量如全局变量static变量不能修饰局部变量。它的作用是强制该变量在编译期初始化完成。适合用在需要确保编译时初始化但不要求变量保持常量的场景中。本篇完感谢阅读
延伸阅读

更多相关文章

2026/10/26 1:25:53

国产AI工具生态全景:从开发到部署的实践指南

1. 国产AI工具生态现状全景2026年的中国AI工具市场已经形成了完整的金字塔结构。底层是基础大模型提供商,中间层是垂直领域解决方案,顶层则是面向终端用户的轻量化应用。与三年前相比,最显著的变化是工具链的国产化率从2023年的37%提升至86%&…

2026/10/26 1:25:53

如何保证数据库与 Redis 的数据一致性

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/26 1:25:53

什么是CSV(周期同步速度模式)和PV(轮廓速度模式)

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/26 2:45:57

Android显示系统架构与性能优化实战

1. Android显示系统架构概述Android显示系统是连接应用层与硬件层的核心桥梁,其设计哲学遵循"分层解耦"原则。从应用开发者视角看,最常接触的是View体系;而从系统层面看,WindowManagerService(WMS)和SurfaceFlinger构成…

2026/10/26 2:45:57

Linux系统日志分析与常用命令实战指南

1. Linux系统日志概述与核心价值日志系统是Linux运维工程师的"黑匣子",记录了系统运行的每一个关键事件。我在实际运维工作中发现,90%以上的故障排查都需要依赖日志分析。不同于Windows系统将日志存储在专用事件查看器中,Linux采用…

2026/10/26 2:45:57

教育数据分析:动态分层评价体系与黑马识别

1. 项目概述:京北中学期中排名分析的价值与意义每次期中考试后的排名公布,都是检验教学成果与学习成效的重要时刻。2026年京北中学的期中排名尤其值得关注,因为这所百年名校正在经历教学改革的关键时期。作为长期跟踪教育数据的从业者&#x…

2026/10/26 2:45:57

GY-AS7262/AS7263六通道光谱模块选型与调参避坑

简介:GY-AS7262 7263 配套资料包面向嵌入式开发、电子制造与传感器应用学习者,围绕 AS7262/AS7263 光谱传感模块的 Arduino 上手与二次开发整理。资源包含15个文件,约1.5MB,以3份PDF数据手册与原理图、3个ino示例程序、2份md说明、…

2026/10/26 2:45:57

AI测试助手:提升系统工程效率的智能解决方案

1. 项目概述:AI测试助手如何赋能系统工程师在系统工程的复杂世界里,每个决策都可能引发连锁反应。三年前我在一次数据中心迁移项目中,因为一个未被发现的兼容性问题导致整个系统宕机8小时,那次教训让我意识到:传统测试…

2026/10/26 2:40:57

UNet图像分割实战:PyTorch实现、训练链路与损失函数选型

先说个我自己的经历:去年帮人做一个细胞显微图像的分割练手项目,需求很朴素——把视野里每一张细胞膜轮廓都描出来,输出一张和原图同尺寸的二值掩膜。我第一反应就是 UNet,从拉代码到跑出第一版能看的结果,前后不到十分…

2026/10/26 0:20:20

全国计算机二级C语言真题PDF高效刷题指南

简介:这份PDF是全国计算机二级C语言考试的试题与答案解析,专为备考二级C语言的考生准备。内容涵盖C语言特点与设计理念、程序基本组成单位、main函数执行流程、函数嵌套调用规则、标识符命名规范、整型实型字符型数据类型、八进制十六进制数合法形式、运…

2026/10/26 1:53:47

requests+BeautifulSoup:爬虫抓取h1标题的入门实战指南

简介:一份以实战为导向的Python爬虫入门资源,面向具备基本编程基础、希望快速掌握网络数据抓取的初学者,可解决从零编写简单爬虫的常见困惑。实例以requests库发送HTTP请求、BeautifulSoup解析HTML文档,完整演示从网页中提取 标题…

2026/10/26 0:20:17

递推最小二乘参数辨识MATLAB编程:二阶系统与渐消记忆实现

简介:这是一篇面向控制系统、信号处理与机器学习等领域学习者的最小二乘参数辨识程序说明文档。资源共包含一个docx格式文档,压缩包大小七十八KB,内容围绕递推最小二乘算法和渐消记忆最小二乘算法展开:先构造一个极点位于单位圆内…

2026/10/26 0:00:48

Nested Learning:解决AI灾难性遗忘的分层记忆架构

1. 为什么AI需要"记忆"能力?在传统深度学习模型中,我们常遇到一个根本性问题:模型在处理新任务时,往往会完全遗忘之前学到的知识。这种现象被业界称为"灾难性遗忘"(Catastrophic Forgetting)。想象一下&#…

2026/10/26 0:00:48

企业级大模型应用:OCR预处理、Dify编排与DeepSeek落地实战

1. 这不是“用大模型”,而是重构工作流的起点“大模型的应用和工具”——这八个字现在被贴在无数技术分享、招聘JD、内部立项书的标题栏里,但绝大多数人点进去后看到的,是零散的API调用示例、几个开源UI截图、或者一句“接入LLM就能降本增效”…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑