news 2026/3/24 22:18:32

constexpr 和 explicit 在 C++ 中被提出的动机

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
constexpr 和 explicit 在 C++ 中被提出的动机

相关内容参考:C++中constexpr 与 explicit关键字使用详解


1.constexpr——“让编译器做更多事”

提出动机:提升性能,减少运行时开销

在 C++11 之前:

  • 只有const,但const 不保证编译期求值
  • 想要编译期常量,只能用#defineenum——都不够安全、不支持函数、不支持复杂类型

因此提出constexpr解决两个痛点:

痛点1:需要真正的编译期常量(strong compile-time constant)

例如:

constintN=foo(10);// 不能保证 foo(10) 在编译期运行intarr[N];// 可能无法作为数组大小

C++ 希望:如果值能在编译期确定,就应该在编译期确定。


痛点2:需要编译期可执行的函数(constexpr function)

例如:

doublearea(doubler){return3.14159*r*r;}constexprdoubleA=area(10);// C++03 之前不行

C++ 希望:

  • 数学函数
  • 小工具函数
  • 初始化对象
  • 甚至类构造函数

都能在编译期执行。


constexpr给 C++ 带来的核心能力

编译期执行函数(Compile-time evaluation)

极大提高运行效率 + 常量折叠 + 去掉运行时开销。

更强的类型安全

#define可靠得多。

用于模板元编程(metaprogramming)

constexpr让模板元编程更直观,不必写复杂的 TMP 结构体推导。

允许类的编译期构造

例如:

structVec3{doublex,y,z;constexprVec3(doublex,doubley,doublez):x(x),y(y),z(z){}};

③ 总结——constexpr 提出的根本动机

让编译器“成为运行时”,能提前计算任何能计算的东西,提高性能与安全性,增强 C++ 的表达能力。

一句话:

constexpr = 让 C++ 从运行时语言 → 编译期可计算语言


2.explicit——“拒绝隐式转换导致的灾难”

提出动机:防止隐式类型转换引发 bug

在 C++98 之前:

构造函数可以隐式调用,导致非常多的意外错误:

structVec{Vec(intx){}// 可隐式转换};Vec v=5;// ??? 编译器会自动调用 Vec(5)

问题:

  • 难以察觉的隐式转换
  • 编译器默默干了不想要的事
  • 操作符重载时尤其危险

如:

booloperator==(constVec&,constVec&);Vec v;boolt=(v==10);// 会被隐式转成 Vec(10)

这是非常危险的行为。


② explicit 的目标:禁止不安全的隐式构造

explicitVec(intx);

禁止:

Vec v=5;// 不再允许

保留:

Vecv(5);// 明确构造

③ explicit 的更高层动机(C++11 之后)

C++11 支持:

  • explicit用于转换运算符
  • explicit(false)/explicit(true)(C++20)

用于禁止 “过度智能” 的隐式行为。

例如:

explicitoperatorbool()const;

防止:

Vector v;if(v){}//intx=v+1;// 防止自动转 bool 再转 int 的怪行为

④ 总结——explicit 提出的根本动机

explicit 的目的就是阻止编译器做你没说过的隐式转换,避免隐式构造引发隐蔽 bug。

一句话:

explicit = 禁止偷偷摸摸的隐式转换,保护你不被语言陷阱坑死。


对比总结

关键字核心动机解决的问题
constexpr让编译期可以计算更多东西,提高性能与安全性编译期常量、constexpr 函数、constexpr 构造函数
explicit禁止隐式转换,减少意料之外的 bug防止构造函数隐式调用,防止隐式转换

3constvsconstexpr对比

C++ 中constconstexpr都与常量相关,但用途和能力差异非常大:

特性constconstexpr
定义声明一个值不可修改声明一个值或函数可以在编译期求值
是否保证编译期不保证,可能运行时初始化保证,如果满足条件,必须在编译期计算
适用对象变量、成员、函数返回值变量、成员、函数、构造函数、类常量
初始化可以运行时初始化必须用编译期常量初始化(C++14 起 relax,可有简单运行时计算)
函数const函数限制成员修改(方法级)constexpr函数在编译期求值,并且可用于常量表达式
数组长度const int N = 10; int arr[N];编译器可能支持,但不保证constexpr int N = 10; int arr[N];必定可用于编译期大小
优化运行时常量,编译器可优化编译期常量,可完全消除运行时开销

举例

constinta=5;// 运行时可变对象也可初始化为常量intarr1[a];// 在一些编译器中可行,但非标准保证constexprintb=5;// 编译期常量intarr2[b];// 标准保证可用

函数对比

constintsquare_const(intx){returnx*x;}// 运行时求值constexprintsquare_constexpr(intx){returnx*x;}// 编译期求值可能
  • square_constexpr(3)→ 编译期可求值
  • square_const(3)→ 编译期不保证,只能运行时求值

4explicit在模板类 / 复杂构造中的用法

explicit最初是为了防止隐式类型转换,但在模板类 / 泛型编程中尤其重要:


① 模板类单参数构造

template<typenameT>structWrapper{explicitWrapper(T val):value(val){}T value;};Wrapper<int>w1(5);// 明确构造Wrapper<int>w2=5;// 错误,禁止隐式转换

在模板类中,如果不加explicit,可能会导致意想不到的隐式类型转换,尤其当模板参数为复杂类型(比如矩阵、点云类型)时。


② 多参数模板构造 + 默认参数

template<typenameT>structPoint{explicitPoint(T x=0,T y=0,T z=0):x(x),y(y),z(z){}T x,y,z;};Point<int>p1(1,2,3);// 明确构造Point<int>p2;// 默认参数构造Point<int>p3={};// 禁止隐式列表初始化

explicit可以避免模板类在列表初始化 / 隐式转换时产生不安全行为。


explicit与转换运算符(C++11+)

C++11 引入了explicit operator,用于模板类中的类型安全转换:

template<typenameT>structVec{T x,y;explicitoperatorbool()const{returnx!=0||y!=0;}};Vec<int>v{0,0};if(v){}// 允许intn=v;// 禁止隐式转换
  • 模板类中尤其重要,因为模板类型可能变化,不加explicit很容易产生隐式转换错误。

④ 小结

  1. const vs constexpr

    • const= 不可修改(可能运行时求值)
    • constexpr= 编译期求值,可用于模板/数组/常量初始化
  2. explicit 在模板类中

    • 防止单参数模板构造产生隐式类型转换
    • 避免列表初始化 / 默认参数带来的隐式调用
    • 可用于转换运算符,增加类型安全性

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/23 13:31:42

10、企业 Linux 系统网络配置全攻略

企业 Linux 系统网络配置全攻略 在当今时代,很难想象一台未连接到互联网或局域网(LAN)的个人电脑。要让企业 Linux 系统连接到 LAN 或互联网,每台 PC 都需要安装并正确配置网络接口卡(NIC)。下面将详细介绍如何使用 Red Hat Enterprise Linux 提供的图形化网络配置工具来…

作者头像 李华
网站建设 2026/3/19 22:26:34

魔兽争霸III终极优化指南:WarcraftHelper全方位性能提升方案

魔兽争霸III终极优化指南&#xff1a;WarcraftHelper全方位性能提升方案 【免费下载链接】WarcraftHelper Warcraft III Helper , support 1.20e, 1.24e, 1.26a, 1.27a, 1.27b 项目地址: https://gitcode.com/gh_mirrors/wa/WarcraftHelper 想要在经典游戏《魔兽争霸III…

作者头像 李华
网站建设 2026/3/23 20:51:48

20、企业级Linux系统维护与用户管理指南

企业级Linux系统维护与用户管理指南 1. Web服务器设置与重启 在配置Web服务器时,可在相应字段输入另一个数字来设置接受的请求数量。对于每个连接的请求,勾选“允许持久连接”复选框可使“下一次连接超时”值生效,该值以秒为单位,服务器在关闭会话前会等待此时间。不过,…

作者头像 李华
网站建设 2026/3/19 8:16:49

70亿参数重构交互体验:Qwen2.5-Omni引爆全模态实时交互革命

70亿参数重构交互体验&#xff1a;Qwen2.5-Omni引爆全模态实时交互革命 【免费下载链接】Qwen2.5-Omni-3B 项目地址: https://ai.gitcode.com/hf_mirrors/Qwen/Qwen2.5-Omni-3B 导语 阿里巴巴通义千问团队于2025年3月开源的Qwen2.5-Omni多模态大模型&#xff0c;以70亿…

作者头像 李华
网站建设 2026/3/24 7:43:55

26、红帽企业 Linux 安装全流程指南

红帽企业 Linux 安装全流程指南 1. 网络连接所需信息 若要将红帽企业 Linux 计算机连接到网络,你需要以下信息: - 计算机的主机名 - 网络的域名 - 计算机的互联网协议(IP)地址(若 IP 地址由 DHCP 服务器提供,则需服务器地址) - 网关地址 - 名称服务器的 IP 地址 …

作者头像 李华
网站建设 2026/3/24 6:12:21

告别API测试协作困境:Bruno请求链实现CI/CD无缝集成

告别API测试协作困境&#xff1a;Bruno请求链实现CI/CD无缝集成 【免费下载链接】bruno 开源的API探索与测试集成开发环境&#xff08;作为Postman/Insomnia的轻量级替代方案&#xff09; 项目地址: https://gitcode.com/GitHub_Trending/br/bruno 在团队自动化测试实践…

作者头像 李华