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

【C++】C++17结构化绑定、std::optional、std::variant、std::any

二十二、C++17中的结构化绑定、std::optional、std::variant、std::any

本部分是一个小系列,介绍C++17中新引入的、用来解决各种不同返回情况的、标准库新组件。

1、C++的结构化绑定
结构化绑定structured bindings是C++17中引入的一项特性,它允许开发者方便地从元组、结构体或数组中解包数据到单独的变量。是在元组(tuple)和对组(pairs)的基础上,新扩展的一种处理多返回值的新方法。

下面例子是我用一个函数返回一个tuple元组,我是如何取出元组中的各个元素的,也就是如何解包的:

其实在C++中处理多个返回值,我这篇博文 【C++】C++中如何处理多返回值、C++中的模板、宏_如何在c 十十 中处理返回值?-CSDN博客 已经介绍过了好几种方法,感兴趣的同学可以自行查看。这里的前两种方式不限于C++标准的版本,但是第三种结构化绑定只适用于C++17标准。所以要使第三种解包方式顺利通过编译,就得在visual studio的property页面里面设置为C++17标准,如上右图所示。

如果说本部分处理的都是确定的、多个返回值,那么对于不确定个数的返回值如何处理呢?就是下面的小标2如何处理optional数据。

2、如何存储可能存在也可能不存在的数据:std::optional
对于返回值不确定时,我们就得用std::optional了。std::optional也是C++17标准中新引进的模板类类型,用于处理那些可能存在也可能不存在的数据。要使用std::optional,首先需要包含头文件。

比如我们现在要写一个函数,这个函数的功能是读取一个文件,那这个文件是否存在?数据是否是我们期望的格式?函数是否正常读取了这个文件?此时这个函数的返回就是一个不确定的数据,可能有返回数据,也可能没有返回数据,也可能需要返回多个数据。
如果正常读取了,那就不用返回什么;如果文件就不存在,那就得返回一个能说明文件是存在还是不存在的东西;如果文件格式不正确,那得返回一个格式不正确的说明。所以函数的返回不是很确定的这种场景,就得用std::optional了。

我们先写一个不用optional的函数:

这种写法就很被动。当读取不成功时,我们也不知道什么原因,是路径错了还是格式错了,还是路径格式都没错,只是文件里面确实就是没数据,所以啥也没读出来。下面我们看看使用optional能多大程度解决这些问题:

可见使用optional代码要稍微清晰一些了,如果文件没打开或者文件格式没对,就没读到文件,我们可以用value_or解释一下返回的空字符是怎么回事。 下面是optional操作符的简单介绍:

3、如何在一个变量中存储多种类型的数据:std::variant
这也是C++17新标准库中提供给我们的模板类:std::variant。它的作用是让我们不用担心处理的确切数据类型。
我们要做的就是指定一个叫做std::variant的类型,然后列出它可能的数据类型。比如你正在解析一个文件,你不确定这是一个字符串还是一个整数还是浮点数或者是布尔数,你就把所有可能的类型都列出来。下面是variant的操作符:

下面我们用代码来说明variant的用法:

从上图variant类型对象的大小可以看出,variant对象的大小是所有类型的大小之和。确切的说是内存对齐后的大小之和。可见,variant是结构体或者类包装而来的。就是其实每种类型它都是分配了对应的内存空间了的。

而与variant非常相似的union可并不是这样的,union分配的内存是所有可能类型数据中的最大那个类型的空间大小。所以variant和union是有本质区别的。也就是说variant是将所有可能的数据类型存储为单独的变量、作为单独的成员。而union则是所有可能的数据类型共享一个内存空间。

可见variant是给我们创建了一个结构体或类,它只是将这可能的多种数据类型存储成那个类或者结构体的成员。
也所以,从技术上讲,union更有效率,但variant更加类型安全,不会造成未定义行为。

前面读取文件的例子,我们使用optional也没有很完美的写出清晰的逻辑,现在我用variant再写这个例子:

此时是不是逻辑就清晰很多、代码也优雅很多!这就是variant的使用场景。

4、如何存储任意类型的数据:std::any
就是在C++单个变量中存储任意类型的数据:std::any,这也是C++17的全新处理方式。
std::variant是需要列出你可能用到的所有类型。而std::any是不需要声明任何类型:

可见,any类型的变量在声明和初始化时,就可以完全不用管变量的类型,只有当你要解码这个变量时才需要这个变量的真正的类型。

variant让我们列出所有可能用到的类型,然后它背后是悄悄生成一个包含了所列的类型的结构体或者类,所以variant是类型安全的。

而从any的源码看,对于小类型small type(就是最底层的那些类型),any的底层和variant是完全相同的。对于大类型(就是复杂的类型),any会动态分配内存,使用void*存储到大存储空间。动态分配内存不利于性能。就是说,如果你在小类型上,比如int, float,甚至vector类或者类似的比如math库等等,使用variant或者any都一样,因为它们都是相同的工作原理。但是如果你需要更多的存储空间,any会动态分配,但variant不会。话说回来就是variant在处理较大数据时会执行得更快,因为避免了动态分配内存。

最后再展示一下any是如何动态分配内存的:

超过32个字节,any就开始动态分配内存了。所以,any是来搞笑的吗?一般不建议经常使用。

相关文章:

【C++】C++17结构化绑定、std::optional、std::variant、std::any

二十二、C17中的结构化绑定、std::optional、std::variant、std::any 本部分是一个小系列,介绍C17中新引入的、用来解决各种不同返回情况的、标准库新组件。 1、C的结构化绑定 结构化绑定structured bindings是C17中引入的一项特性,它允许开发者方便地…...

C#的起源。J++语言的由来?J#和J++傻傻分不清?

C#的起源 C#读音是C Sharp, 它是微软为了对抗Java而生,最早是J,效率比Java还好,后来被Sun公司起诉J破坏了平台无关性,微软重新开发C#. C#和Java一样都定位为中间件语言,用虚拟机执行编译的字节码以达到跨平台目的。从语…...

Flutter 在 对接 google play 时,利用 android studio 可视化生成 已签名的aab包

android studio 可视化生成 aab包 第一 : 先说注意事项 在Flutter项目里面,直接打开当前项目是不行的,不显示相应操作,需要在Android 目录打开,直白点就是直接打开项目里面的Android 目录 不然会出现的一些问题 第一…...

使用web.dev提供的工具实现浏览器消息推送服务

文章目录 前言实现工具和效果实现原理实现过程前端接收用户订阅请求将用户订阅信息更新到后端后端实现接收并保存订阅信息的接口后端实现消息推送的逻辑前言 对于电商独立站来说,新品上架或者促销活动上线及时通知到用户是很重要的,通知的渠道有很多,其中就包括浏览器消息推…...

计算机系统结构为什么用architecture 而不是structure?

architecture本意是建筑学、建筑艺术,其含义就是建筑的样子和背后的设计思想,用于计算机科学可以表达计算机的系统结构和后面的设计原理:它长什么样?它为什么长这样? 与architecture 对应的词是structure &#xff08…...

sqoop问题汇总记录

此篇博客仅记录在使用sqoop时遇到的各种问题。持续更新,有问题评论区一起探讨,写得有不足之处见谅。 Oracle_to_hive 1. main ERROR Could not register mbeans java.security.AccessControlException: access denied ("javax.management.MBeanTr…...

Git 创建新的分支但清空提交记录

有时候需要创建新的分支,但是原有分支的提交非常多,不好区分哪些是创建分支之后的提交。 那么就把原分支的提交全部去掉 要从 分支1 创建 分支2,并确保 分支2 不包含任何提交历史,同时文件与 分支1 的最后一次提交一致&#xff0…...

SQL PRIMARY KEY

SQL PRIMARY KEY 概述 在关系型数据库中,主键(PRIMARY KEY)是一个非常重要的概念。它是表中每一行数据的唯一标识符,用于保证数据的完整性和准确性。本文将详细介绍SQL中的主键,包括其定义、作用、如何创建和修改主键…...

软件测试学习笔记丨Flask操作数据库-对象与数据模型

本文转自测试人社区,原文链接:https://ceshiren.com/t/topic/23440 对象与数据模型 数据模型:是数据特征的抽象,抽象层次上描述了系统的静态特征、动态行为和约束条件,为数据库系统的信息表示与操作提供一个抽象的框架…...

IntelliJ IDEA使用 MybatisX-Generator 插件 自动生成Entity+Mapper+Mapper.xml等代码

一、Intellij安装MybatisX插件: 首先点击 Intellij->Preference->Plugins,然后搜索MybatisX,点击安装: 2 打开数据库 在IntelliJ IDEA 连接Mysql数据库,选择表,点击右键,选择 Mybatis…...

vue中如何为不同功能设置不同的默认打印设置(设置不同的打印机)

浏览器自带的window.print 功能较简单,这里使用LODOP露肚皮打印 以下是vue2示例: 从官网中下载Lodop和C-Lodop官网主站安装包并安装到本地电脑可以全局搜索电脑找到安装文件LodopFuncs.js,也可以直接复制我贴出来的文件 //用双端口加载主JS…...

经纬恒润INTEWORK-VBA新版本正式发布

在汽车电子研发领域,随着开发测试的深入,工程师们常常面临着一个共同的问题:如何高效地在多样化的开发测试场景中切换,并确保不同工具间的紧密协作。不同场景、不同工具的切换与使用给工程师带来高昂的学习成本和前后端信息传递的…...

金蝶云数据集成至MySQL的高效解决方案

金蝶云数据集成至MySQL的高效解决方案 金蝶云星空数据集成到MySQL的技术案例分享 在企业信息化过程中,数据的高效集成和管理是关键环节。本文将聚焦于一个具体的系统对接集成案例:金蝶云星空的数据如何通过轻易云数据集成平台无缝对接到MySQL数据库。本…...

Day02 C++ 环境设置

2024.11.1 C 环境设置 如果您想要设置 C 语言环境,需要确保电脑上有以下两款可用的软件,文本编辑器和 C 编译器。 一、文本编辑器 通过编辑器创建的文件通常称为源文件,源文件包含程序源代码。 C 程序的源文件通常使用扩展名 .cpp、.cp 或…...

AQS是什么

AQS:AbstructQueuedSynchronizer是java.util.concurrent.locks包中的一个类,是多线程同步器,J.U.C包中的多个组件的底层实现都使用到了它。如:Lock、CountDownLatch、Semaphore. 从本质上来说AQS实现了两种机制的锁,排…...

Spring IOC容器简介

Spring IoC(Inversion of Control,控制反转)容器是Spring框架的核心组件之一,负责管理应用程序中的对象及其依赖关系。IoC容器通过依赖注入(Dependency Injection,DI)实现对象的创建、配置和管理…...

【backstopjs】入门安装环境

1.首先全局安装BackstopJS npm install -g backstopjs 安装失败,常见报错&解决办法: 报错: (venv) D:\workspace\Otaku\backstop>npm install -g backstopjs npm warn deprecated inflight1.0.6: This module is not supported, and leaks mem…...

LocalDate 类常用方法详解(日期时间类)

LocalDate 类常用方法详解 LocalDate 是 Java 8 引入的日期时间API中的一个类,用于表示不含时间和时区的日期(年、月、日)。以下是一些常用的 LocalDate 方法: 创建 LocalDate 实例 now():获取当前日期 LocalDate t…...

kmp desktop实现excel预览

先将excel转paf https://blog.csdn.net/qq_42761569/article/details/121699594 package utilimport com.aspose.cells.License import com.aspose.cells.PdfSaveOptions import com.aspose.cells.Workbook import com.geolo.desktop.common.utils.LogUtils import java.io.Fi…...

OB_GINS_day3

这里写目录标题 实现当前状态初始化实现预积分的初始化由于此时preintegration_options 是3(也就是考虑odo以及earth rotation)为预积分的容器添加需要积分的IMU积分因子接下来是添加新的IMU到preintegration中 实现当前状态初始化 这个state_curr的主要…...

dumper.js性能优化:大型对象检查的10个实用技巧

dumper.js性能优化:大型对象检查的10个实用技巧 【免费下载链接】dumper.js A better and pretty variable inspector for your Node.js applications 项目地址: https://gitcode.com/gh_mirrors/du/dumper.js dumper.js是一款为Node.js应用打造的变量检查工…...

代码随想录算法第五十三天| KamaCoder110字符串迁移、KamaCoder105有向图的完全联通、KamaCoder106海岸线的计算

KamaCoder 110 字符串迁移 题目链接:110.字符串迁移 文档讲解:代码随想录 视频讲解: 字符串迁移 思路与感想:直接卡在读懂题意这一关了,我还纳闷输出结果怎么跟自己理解的差那么多。卡哥讲完之后才明白题目的推导过程…...

北京做网站SEO优化有什么技巧_北京做网站关键词优化需要多长时间

北京做网站SEO优化有什么技巧 在北京这样一个竞争激烈的市场,做网站SEO优化显得尤为重要。SEO(Search Engine Optimization,搜索引擎优化)是提升网站在搜索引擎结果中排名的关键手段,而北京的市场竞争尤其激烈&#x…...

OpenClaw备份策略:Qwen3-32B配置与技能库容灾方案

OpenClaw备份策略:Qwen3-32B配置与技能库容灾方案 1. 为什么需要备份OpenClaw环境 去年冬天的一个深夜,我的OpenClaw自动化脚本突然停止工作。经过排查发现是SSD故障导致~/.openclaw目录损坏,丢失了精心调校的模型配置、技能库和任务历史记…...

通信基础复习+重要知识点记忆

你这段理解整体非常对,我帮你把每一步的专业名字、对错、细节都理顺,让你彻底闭环:1. 比特流 0101 → 方波基带波形 m(t)这一步叫:线路编码 / 基带成形你说的单极性码,就是一种最基础的线路编码。输入:0101…...

4大技术方案解决WarcraftHelper工具的《魔兽争霸III》兼容性与性能优化问题

4大技术方案解决WarcraftHelper工具的《魔兽争霸III》兼容性与性能优化问题 【免费下载链接】WarcraftHelper Warcraft III Helper , support 1.20e, 1.24e, 1.26a, 1.27a, 1.27b 项目地址: https://gitcode.com/gh_mirrors/wa/WarcraftHelper WarcraftHelper是一款专注…...

DAY3--SQL单字段去重查询

SQL基础入门:电商用户数据单字段去重查询实操 这一章能解决什么电商工作问题? 前两章我们学了SELECT *(全量看数据)和SELECT 字段列表(精准取字段)。这一章讲的是另一个高频操作:去重。 我讲一个…...

PX4飞控解锁失败?别慌!手把手教你用QGroundControl地面站排查15种常见黄灯警报

PX4飞控解锁失败?别慌!手把手教你用QGroundControl地面站排查15种常见黄灯警报 当你满怀期待地准备让无人机起飞,却发现PX4飞控持续闪烁黄灯拒绝解锁时,那种挫败感我深有体会。作为从菜鸟阶段一路摸爬滚打过来的飞手,我…...

基于深度学习的隧道缺陷检测系统(YOLO12/11/v8/v5模型+django)(源码+lw+部署文档+讲解等)

摘要随着城市化进程的加快,隧道的建设和维护日益重要。隧道缺陷的及时检测与修复不仅关系到交通安全,也涉及到基础设施的耐久性和经济效益。传统的隧道缺陷检测方法依赖人工巡检,效率低且容易遗漏细微缺陷。本文提出了一种基于深度学习的隧道…...

**发散创新:基于同态加密的隐私保护计算在Python中的实战实现**随

发散创新:基于同态加密的隐私保护计算在Python中的实战实现 随着数据安全需求的不断升级,同态加密(Homomorphic Encryption) 正从理论走向落地。它允许对加密数据直接进行计算,结果解密后与明文计算一致——这为云计算…...