C++17中std::optional的使用

news2025/1/17 3:08:23

      模版类std::optional管理一个可选的(optional)存储值(contained value),即可能存在也可能不存在的值。std::optional的一个常见用例是存储可能失败的函数的返回值。与其它方法相反(例如std::pair<T, bool>),std::optional可以很好地处理构造成本高昂的对象,并且更具可读性,因为意图被明确表达。
      在任何给定时间点的std::optional的任何实例要么存储值,要么不存储值。如果std::optional存储一个值,则保证该值作为std::optional对象占用空间的一部分进行分配,即不会发生动态内存分配。
      当std::optional<T>类型的对象根据上下文转换为bool时,如果该对象存储一个值,则转换返回true;如果不存储值,则转换返回false。
      和std::variant、std::any一样,std::optional对象有值语义,其拷贝操作会被实现为深拷贝。std::optional对象也支持move语义
      std::optional模拟了一个可以为空的任意类型的实例,它可以被用作成员、参数、返回值等。

      std::optional提供了一种标准化的方式来表示可选值(optional value),消除了对空指针的需要并增强了代码的可读性。std::optional是使用原始指针或其它机制来表示缺失值或可选值的更安全的替代方案。根据设计,std::optional强制用户在访问某个值之前显式检查该值是否存在,从而最大限度地降低空指针解引用错误的风险。

      std::make_optional:创建一个用参数初始化的std::optional对象。

      std::nullopt是std::nullopt_t类型的常量,用于指示具有未初始化(或空的)状态的std::optional类型,作为std::optional对象无值时候的"值".
      std::optional特别适合延迟初始化问题,它本身就是延迟初始化的一个实例。所存储的T可以在构造时初始化,或者稍后初始化,或者从不初始化。

int test_optional_init()
{
	std::optional<int> var;
	if (!var.has_value())
		std::cout << "var is not set\n"; // var is not set

	var = 8; // error: *var = 8, 因为var采用默认初始化为空
	if (var.has_value())
		std::cout << "var is present: " << var.value() << "\n"; // var is present: 8
	if (var)
		std::cout << "var is present: " << *var << "\n"; // var is present: 8

	std::optional<int> var2{ std::nullopt }; // 将var2初始化置于"empty"状态
	if (!var2.has_value())
		std::cout << "var2 is not set\n"; // var2 is not set

	std::optional<std::string> var3{ "China" };
	if (var3 > std::nullopt)
		std::cout << "var3 > std::nullopt\n"; // var3 > std::nullopt

	auto var4 = std::make_optional<std::vector<char*>>({ "China", "Beijing", "Haidian" });
	for (const auto& v : *var4)
		std::cout << " " << v; //  China Beijing Haidian
	std::cout << "\n";

	// 内建类型可不需指明存储类型,deduction guide
	std::optional var5{ 2 }; 
	std::cout << "var5: " << var5.value() << "\n"; // var5: 2

	std::optional var6{ std::string{"China"} };
	std::cout << "var6: " << var6.value() << "\n"; // var6: China

	return 0;
}

      std::optional成员函数:
      1.访问存储值:
      (1).var.value():返回引用;如果没有值,会抛出std::bad_optional_access异常;
      (2).*var:如果没有值,会crash(or undefined behavior),返回存储值的引用;应该只用于已经确定含有值的场景
      (3).var.value_or:返回值,注意与value()的区别;如果没有值,则获取备选值;
      (4).var->:返回存储值的指针,可访问内部值的成员
      2.emplace:赋予一个新值(in-place);如果在调用之前已经存储一个值,则通过调用其析构函数来销毁所存储的值;
      3.reset:如果存储一个值,则销毁该值;否则,没有任何影响;
      4.has_value:返回std::optional对象是否存有值;
      5.operator bool():返回std::optional对象是否存有值;
      6.swap:交换两个std::optional对象的值;
      非成员函数:比较std::optional对象:operator==, !=, <, <=, >, >=, <=>。比较std::optional对象时,"empty"值即std::nullopt比任何有值的std::optional对象都要小
      std::bad_optional_access:是一个异常类,直接派生自std::exception,用于处理在访问std::optional对象时发生的错误,当尝试访问一个没有存储值的std::optional对象时,会抛出std::bad_optional_access异常。

int test_optional_member_functions()
{
	// 获取std::optional值: var.value(), *var, var.value_or, var->
	std::optional<int> var{ 8 };
	std::cout << "var: " << var.value() << ", " << *var << "\n"; // var: 8, 8
	*var = 6; std::cout << "var: " << *var << "\n"; // var: 6
	var = 8; std::cout << "var: " << *var << "\n"; // var: 8
	*var = 10; std::cout << "var: " << var.value_or(66) << "\n"; // var: 10
	var.reset(); std::cout << "var: " << var.value_or(66) << "\n"; // var: 66

	std::optional<std::string> var2{ "China" };
	std::cout << "var2: " << var2->data() << "\n"; // var2: China

	var.reset(); // or: var = {};
	try {
		std::cout << "var: " << var.value() << "\n";
		//std::cout << "var: " << *var << "\n"; // 直接crash掉
	}
	catch (const std::bad_optional_access& e) {
		std::cout << "exception: " << e.what() << "\n"; // var: exception: Bad optional access
	}

	std::string str{ "Beijing" }; // 不要对常量变量使用std::move
	std::optional<std::string> var3(std::move(str));
	std::cout << "var3: " << var3.value() << ", str: " << str << "\n"; // var3: Beijing, str:

	var3.emplace("Haidian");
	std::cout << "var3: " << var3.value() << "\n"; // var3: Haidian

	if (var3.has_value())
		std::cout << "var3 has value\n"; // var3 has value
	if (var3)
		std::cout << "var3 has value\n"; // var3 has value

	std::cout << "var2: " << var2.value() << ", var3: " << var3.value() << "\n"; // var2: China, var3: Haidian
	var2.swap(var3);
	std::cout << "var2: " << var2.value() << ", var3: " << var3.value() << "\n"; // var2: Haidian, var3: China

	if (var2 != var3)
		std::cout << "var2 != var3\n"; // var2 != var3

	return 0;
}

      执行结果如下图所示:

      GitHub:https://github.com/fengbingchun/Messy_Test

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ETW HOOK原理探析

ETW HOOK研究 文章目录 ETW HOOK研究前言原理探究内核开启ETW日志HOOK ETW修改ETW日志上下文代理GetCpuClock函数寻找SSDT和SSDT Shadow 总结参考 前言 关于ETW是什么我就不多说了&#xff0c;可以通过微软的相关文档了解到。据网上得知这项技术最早被披露于2345的驱动中&…

Netty--ByteBuffer

2. ByteBuffer 有一普通文本文件 data.txt&#xff0c;内容为 1234567890abcd 使用 FileChannel 来读取文件内容 Slf4j public class ChannelDemo1 {public static void main(String[] args) {// FileChannel// 1. 输入输出流&#xff0c; 2. RandomAccessFile// try (F…

反转链表 --- 递归回溯算法练习三

目录 1. 分析题意 2. 分析算法原理 2.1. 递归思路&#xff1a; 1. 挖掘子问题&#xff1a; 3. 编写代码 3.1. step 1&#xff1a; 3.2. step 2&#xff1a; 3.3. step 3&#xff1a; 3.4. 递归代码&#xff1a; 1. 分析题意 力扣原题链接如下&#xff1a; 206. 反转链…

组件的设计原则

目录 插槽的基本概念 基础用法 具名插槽 使用场景 布局控制 嵌套组件 组件的灵活性 高级用法 作用域插槽 总结 前言 Vue 的 slot 是一项强大的特性&#xff0c;用于组件化开发中。它允许父组件向子组件传递内容&#xff0c;使得组件更加灵活和可复用。通过 slot&…

抢量双11!抖音商城「官方立减」 缘何成为“爆单神器”?

10月20日抖音商城双11好物节正式开跑&#xff0c;仅仅三天&#xff0c;抖音商城整体GMV对比去年同期提升了200%&#xff0c;而在开跑一周后&#xff0c;一些品牌的销售额已经超过了今年整个618&#xff0c;可谓增势迅猛。其中&#xff0c;平台官方特别推出的「官方立减」玩法&a…

抢占全球30%碳化硅市场份额!英飞凌押注低碳化和数字化“新时代”

“未来十年将是低碳化和数字化‘双轮驱动’发展的时代。” 英飞凌科技全球高级副总裁及大中华区总裁、英飞凌科技大中华区电源与传感系统事业部负责人潘大伟在英飞凌2023年大中华区生态创新峰会上表示。 当前&#xff0c;“数字化低碳化”新趋势正在席卷和重塑着未来世界的千行…

vue.cli 中怎样使用自定义的组件

目录 创建自定义组件 注册并使用自定义组件 全局注册自定义组件 使用 Props 传递数据 总结 前言 在Vue CLI中使用自定义组件是构建交互式和模块化Web应用的重要一环。Vue CLI为开发者提供了使用自定义组件的灵活性和简便性。通过Vue CLI&#xff0c;你可以创建、注册和使…

UI自动化测试最佳设计模式POM

&#x1f4e2;专注于分享软件测试干货内容&#xff0c;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;交流讨论&#xff1a;加入1000人软件测试技术学习交流群&#x1f4e2;资源分享&#xff1a;进了字节跳动之后&#xff0c;才…

LabVIEW中NIGPIB设备与驱动程序不相关的MAX报错

LabVIEW中NIGPIB设备与驱动程序不相关的MAX报错 当插入GPIB-USB设备时&#xff0c;看到了NI MAX中列出该设备&#xff0c;但却显示了黄色警告指示&#xff0c;并且指出Windows没有与您的设备相关的驱动程序。 解决方案 需要安装能兼容的NI-488.2驱动程序。 通过交叉参考以下有…

WebSphere Liberty 8.5.5.9 (一)

WebSphere Liberty 8.5.5.9 (一) 安装 1. 从官网下载 WebSphere Liberty 8.5.5.9 2. 解压 解压到 D:\wlp-webProfile7-java8-8.5.5.93. 启动 D:\wlp-webProfile7-java8-8.5.5.9\wlp\bin>server start 正在启动服务器 defaultServer。 服务器 defaultServer 已启动。4. …

UWB人员定位系统的原理与应用

uwb定位技术源码 uwb高精度定位系统源码 uwb人员定位系统基于什么原理&#xff1f; UWB人员定位系统基于超宽带(Ultra WideBand)技术进行位置定位。它利用超短脉冲信号&#xff0c;通过测量信号的到达时间差和信号强度等信息&#xff0c;实现对目标位置的定位。UWB技术具有高…

Docker安装详细步骤及相关环境安装配置

目录 一、从空白系统中克隆Centos7系统 二、使用xshell连接docker_tigerhhzz虚拟机 ​编辑 三、在CentOS7基础上安装Docker容器 最近自己在虚拟机上搭建一个docker,将项目运行在虚拟机中。 需要提前准备的工具&#xff0c;XShell(远程链接工具)&#xff0c;VM&#xff08;…

Qt——连接mysql增删查改(仓库管理极简版)

目录 UI布局设计 .pro文件 mainwindow.h main.cpp UI布局设计 .pro文件 QT core gui QT core gui sql QT sqlgreaterThan(QT_MAJOR_VERSION, 4): QT widgetsCONFIG c11# The following define makes your compiler emit warnings if you use # any …

C语言数据结构-----链表类型详解及链表练习题

0.前言 之前我讲解了循序表以及单链表&#xff0c;接下来我会在介绍几个不同的链表&#xff0c;并举例相关习题使大家能够更加深入的理解。 前期内容如下&#xff1a; 链接: 顺序表(动态顺序表增删查改的代码实现) 链接: 单链表(无头单向不循环)增删查改的代码实现 链接: [双向…

带你详细了解git的【分支和标签】

&#x1f3c5;我是默&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; ​​​ &#x1f31f;在这里&#xff0c;我要推荐给大家我的专栏《git》。&#x1f3af;&#x1f3af; &#x1f680;无论你是编程小白&#xff0c;还是有一定基础的程序员&#xff0c;…

使用xlwings实现对excel表中指定列隔行求和

需要对上表中的营业额隔行求和&#xff0c;即橙色背景颜色的求和&#xff0c;无背景颜色的求和。 看了大佬的视频&#xff0c;有两种方法&#xff1a; 1.加辅助列 2.使用判断行的奇偶函数&#xff0c;然后在用sumproduct函数 在此&#xff0c;我使用xlwings对excel表中数据…

来世再不选Java!

危机感 距离上一次找工作面试已经过去快2年了&#xff0c;那时候正值疫情肆虐&#xff0c;虽然还未感受到“寒潮来临”的苗头&#xff0c;但最终还是成功通过了几轮面试&#xff0c;顺利签约。在目前公司待了2年了&#xff0c;在大环境的影响下&#xff0c;没有加薪、没有年终…

经典OJ题:奇偶链表

目录 题目&#xff1a; 示例&#xff1a; 解题思路&#xff1a; 方法一&#xff1a;双链表链接法 图例&#xff1a; 代码演示&#xff1a; 解题效果&#xff1a; 方法二&#xff1a;奇偶指针 图例&#xff1a; 代码演示&#xff1a; 题目&#xff1a; 给定单链表…

vmware开启ipv6

说明 在 ipv4 基础上配置ipv6网络。 分享 大数据博客列表开发记录汇总个人java工具库 项目https://gitee.com/wangzonghui/object-tool 包含json、string、集合、excel、zip压缩、pdf、bytes、http等多种工具&#xff0c;欢迎使用。 vm开启ipv6 设置vmware 打开vmware点击编…

第二章 03Java基础-IDEA相关叙述

文章目录 前言一、IDEA概述二、IDEA下载和安装三、IDEA项目结构介绍四、IDEA的项目和模块操作总结前言 今天我们学习Java基础,IDEA下载以及相关配置和基础使用方法 一、IDEA概述 1.IDEA全称IntelliJ IDEA,是用于Java语言开发的集成工具,是业界公认的目前用于Java程序开发最…