当前位置: 首页 > news >正文

每日一个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。

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

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

http://www.jsqmd.com/news/235786/

相关文章:

  • screen命令在断网环境下的调试应用操作指南
  • [特殊字符]_Web框架性能终极对决:谁才是真正的速度王者[20260112172541]
  • 超详细版LVGL教程:从零实现家居主界面
  • 工业控制面板中LCD1602的布局与驱动技巧
  • 深耕香港会计服务领域 香港卓信会计打造企业注册一站式解决方案
  • 天猫TP公司是什么意思?一般提供哪些服务?
  • RealMem: 重新定义AI的“长期记忆”,挑战真实场景交互
  • 手把手教程:Elasticsearch下载与Logstash环境搭建
  • 【AI机器视觉】MediaPile和YOLO对比
  • MDK与工业自动化集成:系统学习手册
  • 解析USB3.0接口定义引脚说明中的盲埋孔使用技巧
  • Java Web 智能物流管理系统系统源码-SpringBoot2+Vue3+MyBatis-Plus+MySQL8.0【含文档】
  • Elasticsearch客户端集成:应用层对接实战案例
  • USB3.0接口引脚定义详解:从基础到应用完整指南
  • [特殊字符]_高并发场景下的框架选择:从性能数据看技术决策[20260112170745]
  • 微服务分布式SpringBoot+Vue+Springcloud人口老龄化社区活动老年人服务和管理平台
  • Java Web 电影评论网站系统源码-SpringBoot2+Vue3+MyBatis-Plus+MySQL8.0【含文档】
  • UDS多帧传输与流控策略在车内通信的应用
  • 微服务分布式SpringBoot+Vue+Springcloud人脸识别的微信小程序的学生选课签到定位考勤系统
  • Day 28:【99天精通Python】HTML解析库 BeautifulSoup - 像喝汤一样提取网页数据
  • Java Web 车辆管理系统系统源码-SpringBoot2+Vue3+MyBatis-Plus+MySQL8.0【含文档】
  • 一文说清Vitis使用教程在Alveo上的应用要点
  • Day 29:【99天精通Python】数据持久化 - CSV与Excel - 办公自动化的第一步
  • 零基础掌握HardFault异常处理机制的基本原理
  • 微服务分布式SpringBoot+Vue+Springcloud仁康医院预约挂号系统
  • 企业级桂林旅游景点导游平台管理系统源码|SpringBoot+Vue+MyBatis架构+MySQL数据库【完整版】
  • 从零实现内核崩溃分析:WinDbg解析DMP蓝屏文件完整指南
  • HID协议入门指南:常见术语与框架介绍
  • 微服务分布式SpringBoot+Vue+Springcloud受灾区救援物资管理系统优惠
  • L298N典型应用电路搭建手把手教程