现代C++新特性——constexpr

在计算机科学中,字面量(literal)是在源代码中的 value 的文本表示。字面量和变量、常量是同一个级别的概念,常被用于初始化变量。字面量是编译期常量,效率极高。

常量表达式(const expression)是指值不会改变并且在编译过程就能得到计算结果的表达式。显然字面量属于常量表达式,用常量表达式初始化的const 对象也是常量表达式。——C++ primer 5th(中文)59页。

从上面的的这些概念来看常量表达式的出现将一些计算放在编译期进行,从而提高了程序的运行效率。虽然常量表达式可以提高运行时效率,但是在复杂系统中,很难分辨一个表达式到底是不是常量表达式。

constexpr

C++ 11 引入了一个新词 constexpr,其可以用于修饰 对象 和 函数,所产生的效果是不同的。当修饰的是对象时,它的作用就是加强版的 const;当修饰的是函数时,这样的函数在传入编译器常量时,产出编译器常量,在传入运气期值时,产出运行期值。

constexpr 修饰对象

constexpr 修饰对象时的demo:

int sz; // 非 constexpr 变量
constexpr int arraySize1 = sz; // 非 constexpr 变量,sz在编译期未知
constexpr int arraySize2 = 10; // constexpr 变量,10是编译期常量

constexpr 修饰对象时,其值需要在编译期就得到计算,称这样的值的类型为字面类型(literal type)。constexpr 对象因为是编译期常量因此也会产生 const 修饰对象所产生的同样的效果(constexpr 对象都是 const 对象,并非所以 const 对象都是 constexpr 对象)。在 C++11 中,所有除了 void 的内建类型都是字面类型。但是用户自定义型别同样可能也是字面类型(只要声明它的构造函数是 constexpr 就行)。
看下面这个 Point 类就是字面类型:

class Point{
public:
	constexpr Point(double xVal = 0, double yVal = 0) noexcept
	:x(xVal), y(yVal)
	{}
	constexpr double xValue() const noexcept{return x;}
	constexpr double yValue() const noexcept{return y;}
	void setX(double newX) noexcept{x = newX;}
	void setY(double newY) noexcept{y = newY;}
private:
	double x,y;
}

因此就能用 constexpr 修饰用户自定义类型了:

constexpr Point p1(9.4, 27.7);
constexpr Point p2(28.8, 5.3);

constexpr 修饰函数

  • constexpr 函数可以用在要求编译期常量的语境中。在这样的语境中,传入给 constexpr 函数的实参必须都是 constexpr 修饰的变量。
  • 在调用 constexpr 函数时,若传入的参数任何一个或多个在编译期未知,则它的运行方式和普通函数无异。
    看下面的一个小 demo:
constexpr Point midpoint(const Point& p1, const Point& p2) noexcept{
    return {(p1.xValue() + p2.xValue()) / 2,
            (p1.yValue() + p2.yValue()) / 2};
}



int main()
{
    constexpr Point p1(9.4, 27.7);
    constexpr Point p2(28.8, 5.3);
    Point p3{21, 23};

    constexpr Point res1 = midpoint(p1, p2);     // 正确
    constexpr Point res2 = midpoint(p1, p3); // 编译错误
    Point res3 = midpoint(p1, p3);           // 正确
    

    return 0;
}

midpoint 函数就是 constexpr 修饰的函数,当传入的都是编译期常量p1和p2时,midpoint 就会在编译期进行计算且产出 constexpr 修饰的对象;当传入的有一个是非编译期对象 p3 时,midpoint 只会在运行期进行计算,产出非编译期对象 res3。

值得注意的是在 C++ 11 中 constexpr 修饰的成员函数(非全局函数)都隐式得被声明为 const(即该函数不能修改其操作对象的属性。)且它们的返回类型不能是 void。在 C++14 中解除了这两个限制,就连上面类中的成员函数 setXsetY 也能声明为 constexpr

参考

  1. C++中的编译器常量和模板元编程
  2. C++ primer 5th(中文版)
  3. Effective Modern C++(中文版)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/567294.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Electron 30.0.0 发布,升级 Node 和 V8 引擎

近日,Electron 30.0.0 正式发布!你可以通过 npm install electronlatest 进行安装,或者从 Electron 的发布网站下载,继续阅读了解此版本的详细信息。 🔥 主要更新 Windows 上支持 ASAR 完整性融合。如果未正确配置&am…

【后端】python与django的开发环境搭建指南

安装Git 双击Git 客户端安装文件,在安装页面,单击“Next” 在安装路径选择页面,保持默认,单击“Next” 在功能组件选择页面,保持默认,单击“Next” 在开始菜单文件夹设置页面,保持默认&am…

AI交互数字人对教育领域有何优势?

AI交互数字人不仅能够跨越物理距离的限制,以数字人形象为学生提供“面对面”教学互动体验,还能根据学生的具体需求提供个性化的知识解答。如天津大学推出了数字人老师,以刘艳丽教授形象1:1仿真打造的2.5D数字人,能够应…

png图片如何缩小体积?这个方法效果不错

图片压缩是我们生活中经常都会遇到的问题。在日常工作中图片体积过大的话,在使用过程中就会收到影响,比如加载过慢等。那么,当我们想要对png图片进行压缩处理的时候,要怎么操作呢?很简单,使用图片在线压缩&…

单链表逆置(头插法,递归,数据结构栈的应用)

链表逆置就是把最后一个数据提到最前面,倒数第二个放到第二个……依次类推,直到第一个到最后一个。 由于链表没有下标,所以不能借助下标来实行数据的逆置,要靠空间的转移来完成链表的逆置,这里采用没有头节点的链表来实…

Ansible安装基本原理及操作(初识)

作者主页:点击! Ansible专栏:点击! 创作时间:2024年4月23日15点18分 Ansible 是一款功能强大且易于使用的IT自动化工具,可用于配置管理、应用程序部署和云端管理。它使用无代理模式(agentles…

学习笔记:Vue2高级篇

Vue2 学习笔记:Vue2基础篇_ljtxy.love的博客-CSDN博客学习笔记:Vue2中级篇_ljtxy.love的博客-CSDN博客学习笔记:Vue2高级篇_ljtxy.love的博客-CSDN博客 Vue3 学习笔记:Vue3_ljtxy.love的博客)-CSDN博客 文章目录 7.…

STM32 HAL库F103系列之DAC实验(一)

DAC输出实验 原理图 DAC数据格式 DAC输出电压 DORX - 数据输出寄存器 Vref 3.3V 实验简要 1,功能描述 通过DAC1通道1(PA4)输出预设电压, 然后由ADC1通道1 (PA1) 采集,最后显示ADC转换的数字量及换算后的电压值 2,关闭通道1…

【已解决】三菱PLC与电脑通信步骤

前言 现场弄了一下一台三菱FX5U的PLC结果试了半天都没有连接上,后来琢磨了一下终于算是连接上了。报错的截图如下图所示: 解决步骤 第一步:先将自己电脑的IP地址设置到与PLC的IP地址在同一个网段下(前三个是一样,最…

OpenWrt One/AP-24.XY 开源路由器发布,OpenWRT与Banana Pi社区合作

OpenWrt One/AP-24.XY 开源路由器 2024 年,OpenWrt 项目将迎来20 周年!OpenWrt 开源社区官方通过推出社区自己的第一个完全上游支持的硬件设计来庆祝这一周年纪念日。并与联发科,Banana Pi开源社区紧密合作,共同完成硬件的设计与…

C++友元类

友元类 友元类的使用 友元不仅仅适合于友元函数,还可以将类作为友元,在这种情况下,友元类的所有方法都可以访问原始类的私有方法和保护成员,什么时候去使用友元类呢? 两个类之间不存在包含和所属关系,但…

HTML中的文档声明

前言 什么是<!DOCTYPE>&#xff1f;是否需要在 HTML5 中使用&#xff1f;什么是严格模式与混杂模式&#xff1f; 文档声明概念 HTML 文档通常以文档声明开始&#xff0c;该声明的作用是帮助浏览器确定其尝试解析和显示的 HTML 文档类型。 <!DOCTYPE html>文档声…

科技渔业,智慧守护:4G+北斗太阳能定位终端准确定位,防拆卸报警,夯实渔业管理水平

如何高效地管理渔船&#xff0c;有效监控禁渔区域&#xff0c;4G北斗太阳能定位终端应运而生&#xff0c;成为渔业管理的重要应用工具。 我国作为全球渔业的重要国家&#xff0c;渔业一直是沿海地区传统的支柱产业&#xff0c;对经济的繁荣和民生的稳定起着至关重要的作用。因…

STC15L2K60S2-28I-LQFP44 单片机芯片 STC宏晶

STC15L2K60S2-28I-LQFP44 规格信息&#xff1a; 产品类型STC(宏晶) UART/USART2 额定特性- SPI1 USB Device0 USB Host/OTG0 PWM3 I2C&#xff08;SMBUS/PMBUS&#xff09;0 LCD0 工作电压2.4V ~ 3.6V EEPROM 尺度1KB Ethernet0 A/D8x10bit CAN0 D/A3x10bit CPU…

微服架构基础设施环境平台搭建 -(六)Kubesphere 部署Redis服务 设置访问Redis密码

微服架构基础设施环境平台搭建 -&#xff08;六&#xff09;Kubesphere 部署Redis服务 & 设置访问Redis密码 微服架构基础设施环境平台搭建 系列文章 微服架构基础设施环境平台搭建 -&#xff08;一&#xff09;基础环境准备 微服架构基础设施环境平台搭建 -&#xff08;二…

苍穹外卖学习笔记(4.套餐管理,店铺营业状态设置)

目录 一、Redis1、redis在java中的运用 二、店铺营业状态设置1、需求分析设计2、代码设计3、测试 三、套餐管理1、需求设计分析2、代码设计3、测试 一、Redis 具体的redis基本操作就不多再介绍&#xff0c;本节主要学习redis在java中的运用。 1、redis在java中的运用 具体…

Linux之安装Nginx

目录 传送门前言一、快速安装二、反向代理语法1、基本语法2、location语法1. 基本语法2. 匹配规则3. 修饰符4. 权重5. 嵌套location6. 其他指令7.案例 三、配置反向代理 传送门 SpringMVC的源码解析&#xff08;精品&#xff09; Spring6的源码解析&#xff08;精品&#xff0…

【数据结构】AVL树(万字超详细 附动图)

一、前言 二、AVL树的性质 三、AVL树节点的定义 四、AVL树的插入 五、AVL树的平衡调整 六、AVL树的验证 6.1 验证有序 6.2 验证平衡 七、AVL树的删除 八、AVL树的性能和代码 一、前言 还没有学习过二叉搜索树的同学可以移步 【数据结构】二叉搜索树-CSDN博客https:/…

《LINUX运维从入门到精通 》:运维入门者的自学用书

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 公众号&#xff1a;网络豆云计算学堂 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a; 网络豆的主页​​​​​ 写在前面 《Linux运维从入门到精通》从初学者角度…

免费GPU Google Colab保姆级使用攻略,实现数据集快速下载

Colab&#xff08;Colaboratory&#xff09;是一个基于云的交互式开发环境&#xff0c;专为数据科学、机器学习和人工智能任务设计。Colab 由 Google 提供&#xff0c;允许用户在浏览器中直接编写、运行、共享和协作处理 Python代码&#xff0c;特别是那些涉及大数据处理、计算…
最新文章