C++11 constexpr和字面类型:从入门到精通
文章目录
- 引言
- 一、constexpr的基本概念与使用
- 1.1 constexpr的定义与作用
- 1.2 constexpr变量
- 1.3 constexpr函数
- 1.4 constexpr在类构造函数中的应用
- 1.5 constexpr的优势
- 二、字面类型的基本概念与使用
- 2.1 字面类型的定义与作用
- 2.2 字面类型的应用场景
- 2.2.1 常量定义
- 2.2.2 模板参数
- 2.2.3 函数参数
- 2.2.2 模板参数
- 2.2.3 函数参数
- 2.2.4 枚举类型
- 2.3 字面类型的使用技巧
- 2.3.1 使用constexpr
- 2.3.2 尽量避免运行时计算
- 2.3.3 常量折叠
- 三、用户定义字面量
- 3.1 用户定义字面量的概念
- 3.2 定义自定义字面量
- 3.2.1 整数字面量
- 3.2.2 字符串字面量
- 3.3 用户定义字面量的优势
- 四、总结
引言
在C++11标准中,引入了两个非常重要的特性:constexpr
和字面类型。这些特性不仅提升了代码的性能,还增强了代码的可读性和可维护性。对于初学者来说,理解和掌握这些特性是迈向高级C++编程的关键一步。本文将详细介绍constexpr
和字面类型的基本概念、使用方法以及实际应用场景,帮助你从入门到精通。
一、constexpr的基本概念与使用
1.1 constexpr的定义与作用
constexpr
是C++11引入的一个关键字,用于声明可以在编译时计算的常量表达式。它的主要目的是将计算从运行时转移到编译时,从而提高程序的性能。在复杂的系统中,我们常常难以分辨一个初始值是否为常量表达式。而constexpr
允许将变量声明为constexpr
类型,让编译器来验证变量的值是否是常量表达式。例如:
constexpr int i = 200;
constexpr int j = i + 100;
在这个例子中,i
和j
都是在编译时就能确定值的常量表达式。
1.2 constexpr变量
声明为constexpr
的变量一定是一个常量,而且必须用常量表达式初始化。例如:
constexpr int mf = 0; // 0 是常量表达式
constexpr int limit = mf + 1; // mf + 1 是常量表达式
需要注意的是,如果使用函数返回值初始化constexpr
变量,那么该函数必须是constexpr
函数。例如:
constexpr int getSize() { return 10; }
constexpr int size = getSize(); // 正确,getSize是constexpr函数
1.3 constexpr函数
constexpr
函数是指能用于常量表达式的函数。在C++11中,constexpr
函数有一些严格的限制:
- 函数必须返回一个值,所以它的返回值类型不能是
void
。 - 函数体必须只有一条语句:
return expr
,其中expr
必须也是一个常量表达式。如果函数有形参,则将形参替换到expr
中后,expr
仍然必须是一个常量表达式。 - 函数使用之前必须有定义。
- 函数必须用
constexpr
声明。
例如,计算阶乘的constexpr
函数:
constexpr int factorial(int n) { return (n <= 1) ? 1 : (n * factorial(n - 1));
}
当传入的参数是编译时常量时,该函数会在编译时计算结果。例如:
constexpr int result = factorial(5); // 在编译时计算,值为120
1.4 constexpr在类构造函数中的应用
constexpr
还能修饰类的构造函数,即保证传递给该构造函数的所有参数都是constexpr
,那么产生的对象的所有成员都是constexpr
,该对象也是constexpr
对象了,可用于只使用constexpr
的场合。例如:
class Test {
public:constexpr Test(int arg1, int arg2) : v1(arg1), v2(arg2) {}
private:int v1;int v2;
};
constexpr Test A(1, 2);
enum e = {x = A.v1, y = A.v2};
需要注意的是,constexpr
构造函数的函数体必须为空,所有成员变量的初始化都放到初始化列表中。
1.5 constexpr的优势
使用constexpr
带来的好处是多方面的:
- 性能提升:将计算从运行时转移到编译时,减少了运行时的计算开销。例如,在一些需要频繁计算常量的场景中,使用
constexpr
可以显著提高程序的运行速度。 - 类型安全:编译器会对
constexpr
表达式进行严格的检查,确保其在编译时就能得到计算结果,避免了运行时的错误。 - 代码可读性:明确地指出哪些变量和函数是用于编译时常量计算的,使代码更加清晰易懂。例如,在定义数组大小时使用
constexpr
变量,能让其他开发者一眼看出数组大小是在编译时确定的。
二、字面类型的基本概念与使用
2.1 字面类型的定义与作用
字面类型是指可以用于定义常量的数据类型,其值可以在编译时被求值。在C++中,算术类型、引用、指针和某些类都属于字面类型。使用字面类型可以在编译时确定常量的值,提高程序的性能和安全性。例如:
constexpr int max_size = 100; // 声明一个字面类型的常量
2.2 字面类型的应用场景
2.2.1 常量定义
使用字面类型可以定义编译时确定的常量,如数组大小、循环次数等。例如:
template <int N>
void print_array(const int (&arr)[N]) { for (int i = 0; i < N; ++i) {std::cout << arr[i] << " "; }std::cout << std::endl;
}
2.2.2 模板参数
字面类型常量可以作为模板的参数,用于在编译时实例化模板。例如:
template <int N>
struct Array {int data[N];
};
2.2.3 函数参数
字面类型常量可以作为函数的参数,用于传递编译时已知的常量值。例如:
constexpr int add(int x, int y) { return x + y;
}
2.2.2 模板参数
字面类型常量可以作为模板的参数,用于在编译时实例化模板。例如:
template <int N>
struct Array {int data[N];
};
2.2.3 函数参数
字面类型常量可以作为函数的参数,用于传递编译时已知的常量值。例如:
constexpr int add(int x, int y) { return x + y;
}
2.2.4 枚举类型
使用枚举类型来定义一组编译时已知的常量值。例如:
enum class Color { RED, GREEN, BLUE };
2.3 字面类型的使用技巧
2.3.1 使用constexpr
在定义常量时,使用constexpr
关键字以确保它是一个字面类型。例如:
constexpr int result = add(3, 4); // 编译时计算结果
2.3.2 尽量避免运行时计算
使用字面类型可以在编译时进行计算,尽量避免在运行时进行计算,以提高程序性能。例如,在计算数组元素个数时,使用constexpr
函数可以在编译时完成计算。
2.3.3 常量折叠
当多个常量表达式相互作用时,编译器会尽可能地将它们合并为一个更简单的常量表达式。例如:
constexpr int a = 2;
constexpr int b = 3;
constexpr int c = a + b; // 编译器会将a + b合并为5
三、用户定义字面量
3.1 用户定义字面量的概念
在C++11之前,字面量的类型由它们的语法形式决定。C++11引入了用户定义字面量的概念,允许通过定义字面量运算符来扩展这些基本类型的字面量,以支持自定义的类型和行为。例如,我们可以定义一个表示长度的类,并希望能够直接使用字面量来创建这个类的实例,例如,使用15_cm
表示15厘米。
3.2 定义自定义字面量
自定义字面量通过定义一个特殊的字面量运算符来实现。这个运算符以operator""
为前缀,后跟一个唯一的标识符。根据字面量的类型(整数、浮点数、字符、字符串或布尔值),这个运算符可以有不同的形式。
3.2.1 整数字面量
假设我们想要定义一个表示长度的类,并希望能够直接使用字面量来创建这个类的实例,例如,使用15_cm
表示15厘米。首先,定义一个表示长度的类:
class Length { double meters; // 以米为单位
public : explicit Length(double m) : meters(m) { } double toMeters() const { return meters; }
};
然后,定义一个自定义字面量运算符来处理以厘米为单位的长度:
Length operator "" _cm(long double cm) { return Length(cm / 100); // 将厘米转换为米
}
现在,你可以像这样使用自定义字面量:
auto length = 15.0_cm; // 使用自定义字面量创建Length实例
std::cout << "The length is " << length.toMeters() << " meters.\n";
3.2.2 字符串字面量
同样地,我们可以为字符串字面量定义自定义的解析函数。假设我们想要定义一个字面量,用于创建标准化的日期字符串:
std::string operator "" _date(const char* str, size_t len) { // 假设输入的格式为"YYYYMMDD",输出格式为"YYYY-MM-DD" return std::string(str, 4) + "-" + std::string(str + 4, 2) + "-" + std::string(str + 6, 2);
}
使用这个自定义字面量:
auto date = "20230101"_date; // 使用自定义字面量
std::cout << "Formatted date: " << date << std::endl;
3.3 用户定义字面量的优势
- 代码可读性:使代码更加直观,例如在处理时间、长度等单位时,直接使用自定义字面量可以让代码更易理解。
- 类型安全:避免了因手动转换类型而可能出现的错误。
- 可维护性:当需求发生变化时,只需要修改字面量运算符的定义,而不需要修改大量的代码。
四、总结
constexpr
和字面类型是C++11中非常强大的特性,它们为C++程序员提供了更多的编程选择和优化机会。通过使用constexpr
,我们可以将计算从运行时转移到编译时,提高程序的性能;而字面类型和用户定义字面量则增强了代码的可读性和可维护性。在实际编程中,合理运用这些特性可以让我们的代码更加高效、安全和易于理解。希望本文能够帮助你更好地理解和掌握C++11中的constexpr
和字面类型,从而提升你的C++编程水平。
相关文章:

C++11 constexpr和字面类型:从入门到精通
文章目录 引言一、constexpr的基本概念与使用1.1 constexpr的定义与作用1.2 constexpr变量1.3 constexpr函数1.4 constexpr在类构造函数中的应用1.5 constexpr的优势 二、字面类型的基本概念与使用2.1 字面类型的定义与作用2.2 字面类型的应用场景2.2.1 常量定义2.2.2 模板参数…...

EEG-fNIRS联合成像在跨频率耦合研究中的创新应用
摘要 神经影像技术对医学科学产生了深远的影响,推动了许多神经系统疾病研究的进展并改善了其诊断方法。在此背景下,基于神经血管耦合现象的多模态神经影像方法,通过融合各自优势来提供有关大脑皮层神经活动的互补信息。在这里,本研…...
python打卡day49@浙大疏锦行
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 一、通道注意力模块复习 & CBAM实现 import torch import torch.nn as nnclass CBAM(nn.Module):def __init__…...
Qt Quick Controls模块功能及架构
Qt Quick Controls是Qt Quick的一个附加模块,提供了一套用于构建完整用户界面的UI控件。在Qt 6.0中,这个模块经历了重大重构和改进。 一、主要功能和特点 1. 架构重构 完全重写了底层架构,与Qt Quick更紧密集成 移除了对Qt Widgets的依赖&…...
手动给中文分词和 直接用神经网络RNN做有什么区别
手动分词和基于神经网络(如 RNN)的自动分词在原理、实现方式和效果上有显著差异,以下是核心对比: 1. 实现原理对比 对比维度手动分词(规则 / 词典驱动)神经网络 RNN 分词(数据驱动)…...

C++中vector类型的介绍和使用
文章目录 一、vector 类型的简介1.1 基本介绍1.2 常见用法示例1.3 常见成员函数简表 二、vector 数据的插入2.1 push_back() —— 在尾部插入一个元素2.2 emplace_back() —— 在尾部“就地”构造对象2.3 insert() —— 在任意位置插入一个或多个元素2.4 emplace() —— 在任意…...
计算机系统结构复习-名词解释2
1.定向:在某条指令产生计算结果之前,其他指令并不真正立即需要该计算结果,如果能够将该计算结果从其产生的地方直接送到其他指令中需要它的地方,那么就可以避免停顿。 2.多级存储层次:由若干个采用不同实现技术的存储…...
HTML中各种标签的作用
一、HTML文件主要标签结构及说明 1. <!DOCTYPE html> 作用:声明文档类型,告知浏览器这是 HTML5 文档。 必须:是。 2. <html lang“zh”>. </html> 作用:包裹整个网页内容,lang"z…...

CVE-2023-25194源码分析与漏洞复现(Kafka JNDI注入)
漏洞概述 漏洞名称:Apache Kafka Connect JNDI注入导致的远程代码执行漏洞 CVE编号:CVE-2023-25194 CVSS评分:8.8 影响版本:Apache Kafka 2.3.0 - 3.3.2 修复版本:≥ 3.4.0 漏洞类型:反序列化导致的远程代…...
统计学(第8版)——统计抽样学习笔记(考试用)
一、统计抽样的核心内容与问题 研究内容 从总体中科学抽取样本的方法利用样本数据推断总体特征(均值、比率、总量)控制抽样误差与非抽样误差 解决的核心问题 在成本约束下,用少量样本准确推断总体特征量化估计结果的可靠性(置…...

Copilot for Xcode (iOS的 AI辅助编程)
Copilot for Xcode 简介Copilot下载与安装 体验环境要求下载最新的安装包安装登录系统权限设置 AI辅助编程生成注释代码补全简单需求代码生成辅助编程行间代码生成注释联想 代码生成 总结 简介 尝试使用了Copilot,它能根据上下文补全代码,快速生成常用…...

Axure零基础跟我学:展开与收回
亲爱的小伙伴,如有帮助请订阅专栏!跟着老师每课一练,系统学习Axure交互设计课程! Axure产品经理精品视频课https://edu.csdn.net/course/detail/40420 课程主题:Axure菜单展开与收回 课程视频:...
Docker、Wsl 打包迁移环境
电脑需要开启wsl2 可以使用wsl -v 查看当前的版本 wsl -v WSL 版本: 2.2.4.0 内核版本: 5.15.153.1-2 WSLg 版本: 1.0.61 MSRDC 版本: 1.2.5326 Direct3D 版本: 1.611.1-81528511 DXCore 版本: 10.0.2609…...

RabbitMQ 各类交换机
为什么要用交换机? 交换机用来路由消息。如果直发队列,这个消息就被处理消失了,那别的队列也需要这个消息怎么办?那就要用到交换机 交换机类型 1,fanout:广播 特点 广播所有消息:将消息…...

高保真组件库:开关
一:制作关状态 拖入一个矩形作为关闭的底色:44 x 22,填充灰色CCCCCC,圆角23,边框宽度0,文本为”关“,右对齐,边距2,2,6,2,文本颜色白色FFFFFF。 拖拽一个椭圆,尺寸18 x 18,边框为0。3. 全选转为动态面板状态1命名为”关“。 二:制作开状态 复制关状态并命名为”开…...

未授权访问事件频发,我们应当如何应对?
在当下,数据已成为企业和组织的核心资产,是推动业务发展、决策制定以及创新的关键驱动力。然而,未授权访问这一隐匿的安全威胁,正如同高悬的达摩克利斯之剑,时刻威胁着数据的安全,一旦触发,便可…...
Easy Excel
Easy Excel 一、依赖引入二、基本使用1. 定义实体类(导入/导出共用)2. 写 Excel3. 读 Excel 三、常用注解说明(完整列表)四、进阶:自定义转换器(Converter) 其它自定义转换器没生效 Easy Excel在…...

欢乐熊大话蓝牙知识17:多连接 BLE 怎么设计服务不会乱?分层思维来救场!
多连接 BLE 怎么设计服务不会乱?分层思维来救场! 作者按: 你是不是也遇到过 BLE 多连接时,调试现场像网吧“掉线风暴”? 温度传感器连上了,心率带丢了;一边 OTA 更新,一边通知卡壳。…...
AWS vs 阿里云:功能、服务与性能对比指南
在云计算领域,Amazon Web Services (AWS) 和阿里云 (Alibaba Cloud) 是全球领先的提供商,各自在功能范围、服务生态系统、性能表现和适用场景上具有独特优势。基于提供的引用[1]-[5],我将从功能、服务和性能三个方面进行结构化对比分析&#…...
用js实现常见排序算法
以下是几种常见排序算法的 JS实现,包括选择排序、冒泡排序、插入排序、快速排序和归并排序,以及每种算法的特点和复杂度分析 1. 选择排序(Selection Sort) 核心思想:每次从未排序部分选择最小元素,与未排…...
python读取SQLite表个并生成pdf文件
代码用于创建含50列的SQLite数据库并插入500行随机浮点数据,随后读取数据,通过ReportLab生成横向PDF表格,包含格式化(两位小数)及表头、网格线等美观样式。 # 导入所需库 import sqlite3 # 用于操作…...
当下AI智能硬件方案浅谈
背景: 现在大模型出来以后,打破了常规的机械式的对话,人机对话变得更聪明一点。 对话用到的技术主要是实时音视频,简称为RTC。下游硬件厂商一般都不会去自己开发音视频技术,开发自己的大模型。商用方案多见为字节、百…...
大模型真的像人一样“思考”和“理解”吗?
Yann LeCun 新研究的核心探讨:大语言模型(LLM)的“理解”和“思考”方式与人类认知的根本差异。 核心问题:大模型真的像人一样“思考”和“理解”吗? 人类的思考方式: 你的大脑是个超级整理师。面对海量信…...
【题解-洛谷】P10480 可达性统计
题目:P10480 可达性统计 题目描述 给定一张 N N N 个点 M M M 条边的有向无环图,分别统计从每个点出发能够到达的点的数量。 输入格式 第一行两个整数 N , M N,M N,M,接下来 M M M 行每行两个整数 x , y x,y x,y,表示从 …...
在Spring Boot中集成RabbitMQ的完整指南
前言 在现代微服务架构中,消息队列(Message Queue)是实现异步通信、解耦系统组件的重要工具。RabbitMQ 是一个流行的消息中间件,支持多种消息协议,具有高可靠性和可扩展性。 本博客将详细介绍如何在 Spring Boot 项目…...

Element-Plus:popconfirm与tooltip一起使用不生效?
你们好,我是金金金。 场景 我正在使用Element-plus组件库当中的el-popconfirm和el-tooltip,产品要求是两个需要结合一起使用,也就是鼠标悬浮上去有提示文字,并且点击之后需要出现气泡确认框 代码 <el-popconfirm title"是…...

Selenium 查找页面元素的方式
Selenium 查找页面元素的方式 Selenium 提供了多种方法来查找网页中的元素,以下是主要的定位方式: 基本定位方式 通过ID定位 driver.find_element(By.ID, "element_id")通过Name定位 driver.find_element(By.NAME, "element_name"…...

OPENCV图形计算面积、弧长API讲解(1)
一.OPENCV图形面积、弧长计算的API介绍 之前我们已经把图形轮廓的检测、画框等功能讲解了一遍。那今天我们主要结合轮廓检测的API去计算图形的面积,这些面积可以是矩形、圆形等等。图形面积计算和弧长计算常用于车辆识别、桥梁识别等重要功能,常用的API…...
【Java】Ajax 技术详解
文章目录 1. Filter 过滤器1.1 Filter 概述1.2 Filter 快速入门开发步骤:1.3 Filter 执行流程1.4 Filter 拦截路径配置1.5 过滤器链2. Listener 监听器2.1 Listener 概述2.2 ServletContextListener3. Ajax 技术3.1 Ajax 概述3.2 Ajax 快速入门服务端实现:客户端实现:4. Axi…...

spring boot使用HttpServletResponse实现sse后端流式输出消息
1.以前只是看过SSE的相关文章,没有具体实践,这次接入AI大模型使用到了流式输出,涉及到给前端流式返回,所以记录一下。 2.resp要设置为text/event-stream resp.setContentType("text/event-stream"); resp.setCharacter…...