0

0

C++中的constexpr构造函数是什么?(如何构造编译期常量对象)

冰火之心

冰火之心

发布时间:2026-02-12 19:06:42

|

377人浏览过

|

来源于php中文网

原创

constexpr构造函数要求:所有成员必须用常量表达式初始化;函数体在c++11中须为空或仅return,c++14+允许简单语句但全为常量表达式;禁止虚函数、异常、goto等运行时特性;所有调用的函数也须为constexpr。

c++中的constexpr构造函数是什么?(如何构造编译期常量对象)

constexpr构造函数必须满足什么条件

它不是“加个constexpr关键字就能用”的语法糖,而是编译器对构造逻辑的严格审查。只有当整个构造过程能在编译期完全求值、不触发任何运行时行为时,才被允许。

  • 所有成员变量初始化必须通过常量表达式完成,比如不能调用std::time(nullptr)new
  • 函数体必须为空,或只包含return;(C++11);C++14起允许简单语句,但所有操作仍需是常量表达式
  • 不能有虚函数、虚基类、异常处理(try/catch)、goto等运行时机制
  • 所有被调用的成员函数、构造函数也必须是constexpr

典型错误现象:error: constexpr constructor does not initialize all memberserror: call to non-constexpr function

怎么写一个真正可用的constexpr构造函数

核心是“从定义开始就只依赖编译期已知值”。比如封装一个固定长度字符串:

struct FixedString {
    char data[16];
    constexpr FixedString(const char* s) : data{} {
        for (int i = 0; i < 15 && s[i]; ++i) {
            data[i] = s[i];
        }
    }
};
  • 数组大小必须字面量(如[16]),不能是int n参数
  • 初始化列表里用data{}而非data()——后者在C++11中不被视为常量初始化
  • 循环上限必须是常量(15),且不能依赖外部变量
  • 传入的s必须是字符串字面量(如"hello"),否则无法通过编译

常见误用:试图把std::stringstd::vector塞进constexpr构造函数——它们内部用了动态内存,直接报错。

立即学习C++免费学习笔记(深入)”;

TicNote
TicNote

出门问问推出的Agent AI智能硬件

下载

为什么static_assert能检测constexpr对象,而auto却可能失败

因为static_assert强制要求其参数是常量表达式,而auto推导只是类型,不约束求值时机。

  • constexpr FixedString s{"abc"}; → 成功,对象生命周期从编译期开始
  • auto s = FixedString{"abc"}; → 可能退化为运行时构造(尤其在非全局/非constexpr上下文中)
  • static_assert(s.data[0] == 'a'); → 强制验证s是否真为编译期常量

性能影响很直接:真正的constexpr对象,其数据可直接内联进二进制,不占运行时内存;一旦退化,就和普通对象一样要执行构造函数代码。

模板参数 + constexpr构造函数的组合陷阱

这是最容易忽略的复杂点:模板实参本身必须是常量表达式,但构造函数能否参与推导,取决于是否满足constexpr前提。

  • template <size_t n> struct Buf { char d[N]; constexpr Buf() = default; };</size_t> → 合法,N是编译期整数
  • Buf<sizeof> b;</sizeof> → 能工作,因为FixedString{"x"}构造成功,sizeof是常量表达式
  • Buf<strlen> b;</strlen> → 错误!strlen不是constexpr函数(C++20前)

真正难缠的是跨翻译单元的 constexpr 对象引用:如果头文件里声明了extern constexpr FixedString s = {"abc"};,但定义放在.cpp里,链接时可能丢失常量性,导致static_assert失败——这种问题往往只在LTO关闭时暴露。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

708

2023.08.02

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1550

2023.10.24

scripterror怎么解决
scripterror怎么解决

scripterror的解决办法有检查语法、文件路径、检查网络连接、浏览器兼容性、使用try-catch语句、使用开发者工具进行调试、更新浏览器和JavaScript库或寻求专业帮助等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

351

2023.10.18

500error怎么解决
500error怎么解决

500error的解决办法有检查服务器日志、检查代码、检查服务器配置、更新软件版本、重新启动服务、调试代码和寻求帮助等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

326

2023.10.25

go语言goto的用法
go语言goto的用法

本专题整合了go语言goto的用法,阅读专题下面的文章了解更多详细内容。

138

2025.09.05

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

509

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

214

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1550

2023.10.24

c语言 数据类型
c语言 数据类型

本专题整合了c语言数据类型相关内容,阅读专题下面的文章了解更多详细内容。

4

2026.02.12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 9.3万人学习

C 教程
C 教程

共75课时 | 4.7万人学习

C++教程
C++教程

共115课时 | 17.4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号