news 2026/2/6 10:00:57

每日一个C++知识点|const 和 constexpr 的区别

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
每日一个C++知识点|const 和 constexpr 的区别

在程序开发中,由于代码复杂度大或者程序员的疏忽,以及函数参数传递中的无意识修改,都会导致数据意外修改的风险。为了解决这个问题,出现了类型限定符。其中,C++的主要类型限定符是constconstexpr两种。

那么 const 和 constexpr 的区别和联系是什么呢?什么时候用哪一个呢?那么下面分别对这个问题进行解答~

const

早期的 C++ 是对 C 的扩展,而 C 语言中只能通过#define定义常量,比如#define MAX 100,但 #define 是预处理指令,没有类型检查,容易引发隐蔽错误。const 的出现填补了类型安全的只读常量的空白,既能保证数据只读,又能让编译器做类型校验,成为 C++ 的主要类型限定符。

const 作为 C++ 的类型限定符,使用非常广泛,可以修饰普通变量、指针、引用、函数参数、类成员变量、类成员函数、静态成员变量。下面分别对其用法进行举例:

const修饰普通变量

const 修饰普通变量后,变量初始化后不可修改。

const修饰指针

const修饰指针,精细控制只读范围,可以限制指针指向的内容只读,也可以限制指针本身只读,因此分为常量指针指针常量

常量指针:指向常量的指针,指向的内容不可以修改,但指针可以指向其他地方:

指针常量:指针本身是常量,指针指向的内容可以修改,但指针不能指向其他地方:

除此之外,还有一种指针本身和指向的内容都是只读的情况:

const 修饰引用

const 修饰引用,声明只读引用,避免通过引用修改原变量。

修饰参数也同此理~

只读引用可绑定常量,普通引用不行:

const 修饰类成员变量

const 类成员变量必须在构造函数初始化列表中初始化,不能在类内直接赋值,也不能在构造函数体中赋值。

const 修饰成员函数

const 修饰成员函数,保证函数不修改类成员,其语法是成员函数末尾加 const。

具体来说,是保证这个成员函数内部不能修改这个类的成员变量,如下图所示:

其中get_id是类的成员函数,score是类的成员变量。

const 修饰静态成员变量

const 修饰静态成员变量是类级别的只读常量,所有类实例共享这一个值,且值初始化后不可修改,具备 static 和 const 双重的属性,也就是共享只读的属性。

如果尝试修改:编译报错:

以上是 const 的各种使用场景,其核心是只读约束,不同场景的用法本质都是限定其修改权限。

那么我们下面来看看constexpr的用法。

constexpr

constexpr是 C++11 引入的关键字,是常量表达式,就是强制要求修饰的变量、 函数、构造函数能在编译期确定值。

因为const是运行时才限制可读属性,而constexpr是编译期就确定,所以是 const 的 “编译期增强版”。

这种做法的好处是把计算和对象构造提前到编译阶段完成,既提升运行效率,又解锁编译期专属的语法能力,还能提前暴露错误。

constexpr 主要修饰变量、函数、构造函数、类成员等场景,其用法如下:

constexpr修饰变量

constexpr修饰变量时必须用编译期可确定的值初始化,在限制可读方面比const更强,可直接用于数组大小、模板参数等需要编译期常量的场景。

constexpr 修饰函数

constexpr 函数并非必须编译期执行,而是支持编译期执行,只有传入编译期常量参数时,才会在编译期计算;传入运行期参数时,退化为普通函数:

这样做的好处是:既保留了编译期计算的性能优势,又不丧失普通函数的通用性,一份代码能同时满足编译期常量计算运行期动态计算两种场景,避免重复写两套逻辑。

但是编译器的 “自动判断” 可能带来行为不一致、调试难度增加、编译耗时上升等问题。

constexpr 修饰构造函数

constexpr修饰构造函数时,构造函数体必须为空,而且所有成员通过初始化列表初始化,在编译期构造对象;

其中类的成员变量需是 constexpr 兼容类型,比如int、float等。

#include<iostream>usingnamespacestd;classPoint{public:// constexpr 构造函数:编译期初始化成员constexprPoint(intx_,inty_):x(x_),y(y_){}// constexpr 成员函数:编译期获取成员值constexprintget_x()const{returnx;}constexprintget_y()const{returny;}private:intx,y;// 内置类型,支持 constexpr 初始化};intmain(){// 编译期创建 Point 对象constexprPointp(10,20);// 编译期获取成员值(无需运行期调用函数)constexprintx=p.get_x();// x=10constexprinty=p.get_y();// y=20cout<<"Point("<<x<<", "<<y<<")"<<endl;return0;}

constexpr 修饰静态成员变量

constexpr 修饰静态成员变量是 static const 的替代方案,属于类级别的编译期常量,所有实例共享,且不可修改。

不同的是,无需像 static const 那样做 “类内声明 + 类外初始化”

constexpr 最核心的用法是修饰变量和修饰函数,其中修饰变量是编译期常量,修饰函数支持编译期计算,大大提升运行效率。

二者区别

const 和 constexpr 的主要区别在于:const 是通用只读约束符,保证变量和数据初始化后不可修改,但不强制值在编译期确定。而 constexpr 是编译期常量强制符,不仅保证只读,还强制值和计算结果必须在编译期确定。

那么什么场景下用 const ,什么场景下用 constexpr 呢?

const 还是有一定的灵活性的,如用户输入、函数运行结果、类非静态只读成员等这些值需运行期确定,就只能用 const。

constexpr 胜在编译期强制约束,当希望函数和对象在编译期完成计算或者构造来提升运行效率时就用constexpr。

二者的联系

const 和 constexpr 都是为了约束数据的可修改性,提升代码安全性。

其中,constexpr 是 const 的超集,继承了 const 的"只读"特性,还额外增加了"编译期求值”的约束;编译期确定的值优先用 constexpr,仅需只读且值运行期确定时用 const,二者共同覆盖了 C++ 中所有"常量"场景。

总结

本文主要介绍 C++ 的关键字 const 和 constexpr 之间的区别和联系,可以概括为以下几点:

  1. const的作用和使用方法;
  2. constexpr的作用和使用方法;
  3. 仅需"只读"用const,需要"编译期确定值"用constexpr。

以上就是本文的内容,非常感谢您能花出宝贵的时间阅读,如果对您有帮助的话,欢迎点赞收藏~

如果本文存在不足之处甚至错误的地方欢迎大家在评论区多多批评指出, 我一定认真改正~

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

Packet Tracer运行环境配置全面讲解

手把手教你搞定 Cisco Packet Tracer 运行环境&#xff1a;从下载到稳定运行的完整实战指南 你有没有遇到过这样的情况&#xff1f;兴致勃勃地打开网络课作业&#xff0c;准备用 Cisco Packet Tracer 做个路由实验&#xff0c;结果双击图标——黑屏、闪退、弹窗报错&#xf…

作者头像 李华
网站建设 2026/2/4 15:43:27

MDK与工业自动化集成:系统学习手册

MDK与工业自动化集成&#xff1a;从代码到产线的实战指南你有没有遇到过这样的场景&#xff1f;一个工业控制项目&#xff0c;团队里有人写MCU固件&#xff0c;有人做上位机通信&#xff0c;还有人负责PLC逻辑。结果到最后联调时&#xff0c;发现采样周期对不上、Modbus寄存器偏…

作者头像 李华
网站建设 2026/2/5 0:18:15

Jetpack Compose 实战:如何优雅地封装全局弹窗

在开发 Compose 应用时&#xff0c;弹窗管理往往是一个让人头疼的问题。通常会把 Dialog 代码直接写在 UI 组件内部&#xff1a;Composable fun HomeScreen() {var showDialog by remember { mutableStateOf(false) }if (showDialog) {AlertDialog( ... )} }这种写法在简单的 D…

作者头像 李华
网站建设 2026/1/29 1:13:08

USB3.1传输速度为何达不到理论值?图解说明

USB3.1传输速度为何达不到理论值&#xff1f;工程师亲测揭秘你有没有遇到过这种情况&#xff1a;买了一根标着“USB3.1 Gen 2”的高速线&#xff0c;配上NVMe固态硬盘盒&#xff0c;信心满满地开始拷贝4K视频文件——结果任务管理器里的传输速度只显示400 MB/s&#xff0c;连宣…

作者头像 李华
网站建设 2026/2/4 9:43:38

如何通过ITIL运维管理软件打造高效运维体系?

在企业数字化转型加速的背景下&#xff0c;信息技术服务管理&#xff08;ITSM&#xff09;成为企业运营的核心环节。随着业务系统复杂度增加&#xff0c;传统的人工运维模式难以满足快速响应、流程规范和高效管理的需求。ITIL运维管理软件应运而生&#xff0c;通过标准化流程、…

作者头像 李华