【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 (…...
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 的最后一次提交一致࿰…...
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的主要…...
RexUniNLU教育场景实战:学生问答意图识别+知识点槽位定位效果展示
RexUniNLU教育场景实战:学生问答意图识别知识点槽位定位效果展示 1. 引言:当AI老师遇上“十万个为什么” 想象一下这个场景:一个学生正在使用在线学习平台,他输入了一个问题:“老师,为什么三角形的内角和…...
Windows系统安装OpenClaw详解:千问3.5-9B模型联调避坑指南
Windows系统安装OpenClaw详解:千问3.5-9B模型联调避坑指南 1. 为什么选择OpenClaw千问3.5-9B组合 去年我在尝试自动化办公流程时,发现市面上的RPA工具要么功能臃肿,要么需要将敏感数据上传到云端。直到遇到OpenClaw这个开源框架,…...
ToClaw全方位介绍:你的第一只“龙虾”AI助手,一分钟轻松领养!
ToClaw全方位介绍:你的第一只“龙虾”AI助手,一分钟轻松领养! 一、先来聊聊这只“龙虾”的故事 2026年开年,如果问中文互联网最火爆的技术热词是什么,那一定非「OpenClaw」莫属。这个被大家亲切称为“龙虾”的开源项目…...
避坑指南:Oracle EBS AR模块数据查询中的10个常见错误与优化技巧
Oracle EBS AR模块数据查询实战:10个高频错误解析与性能优化指南 当你面对Oracle EBS AR模块的海量数据时,是否经常遇到查询结果不符预期、性能低下甚至系统卡死的困境?作为从业15年的EBS技术顾问,我见过太多团队在AR数据查询上踩…...
陈文自媒体:暗水印功能上线,2类玩家要发财了!
作者陈文,公众号:陈文日记,90后草根创业者,5年自媒体经验,聚焦体育自媒体和小红书商单,关注我,越分享收获越多。 2026年4月了,抖音最牛逼的暗水印上线了,很多千川的老铁麻…...
OpenClaw+gemma-3-12b-it双剑合璧:5个提升效率的真实案例
OpenClawgemma-3-12b-it双剑合璧:5个提升效率的真实案例 1. 为什么选择这个组合? 去年我开始尝试用AI自动化处理日常工作,试过不少方案,最终锁定OpenClawgemma-3-12b-it这个组合。原因很简单:OpenClaw能像真人一样操…...
C++的std--ranges同步问题
C的std::ranges同步问题:现代C的并发挑战 随着C20引入std::ranges,开发者获得了更简洁、更强大的范围操作工具,但在多线程环境下,std::ranges的同步问题逐渐浮出水面。范围适配器、惰性求值和视图的组合虽然提升了代码的表达力&a…...
Zotero文献元数据拯救指南:从混乱到规范的自动化解决方案
Zotero文献元数据拯救指南:从混乱到规范的自动化解决方案 【免费下载链接】zotero-format-metadata Linter for Zotero. A plugin for Zotero to format item metadata. Shortcut to set title rich text; set journal abbreviations, university places, and item …...
无痛人流三天能出门吗?术后出行与身体恢复科学指南
很多女性在无痛人流术后都会关心出行与恢复问题,其中 “无痛人流三天能出门吗” 是高频咨询内容。术后恢复不仅关系到短期舒适度,也影响生殖系统长期健康。结合临床护理经验与行业康复标准,本文对术后出行时机、注意事项及科学修护方式进行客…...
ISO-SLAM-seq:全长 RNA代谢测序服务
ISO-SLAM-seq 技术,是 SLAM-seq 与 ISO-seq 的结合,通过研发成熟的核苷类似物 4-硫尿苷 (S4U) 代谢 RNA 标记方法和基于 Oxford Nanopore Technology 纳米孔测序平台或者 PacBio 的三代全长转录组测序方法,ISO-SLAM-seq 能检测整合到总 RNA 中…...
