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

      模版类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 setvar = 8; // error: *var = 8, 因为var采用默认初始化为空if (var.has_value())std::cout << "var is present: " << var.value() << "\n"; // var is present: 8if (var)std::cout << "var is present: " << *var << "\n"; // var is present: 8std::optional<int> var2{ std::nullopt }; // 将var2初始化置于"empty"状态if (!var2.has_value())std::cout << "var2 is not set\n"; // var2 is not setstd::optional<std::string> var3{ "China" };if (var3 > std::nullopt)std::cout << "var3 > std::nullopt\n"; // var3 > std::nulloptauto var4 = std::make_optional<std::vector<char*>>({ "China", "Beijing", "Haidian" });for (const auto& v : *var4)std::cout << " " << v; //  China Beijing Haidianstd::cout << "\n";// 内建类型可不需指明存储类型,deduction guidestd::optional var5{ 2 }; std::cout << "var5: " << var5.value() << "\n"; // var5: 2std::optional var6{ std::string{"China"} };std::cout << "var6: " << var6.value() << "\n"; // var6: Chinareturn 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: 6var = 8; std::cout << "var: " << *var << "\n"; // var: 8*var = 10; std::cout << "var: " << var.value_or(66) << "\n"; // var: 10var.reset(); std::cout << "var: " << var.value_or(66) << "\n"; // var: 66std::optional<std::string> var2{ "China" };std::cout << "var2: " << var2->data() << "\n"; // var2: Chinavar.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::movestd::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: Haidianif (var3.has_value())std::cout << "var3 has value\n"; // var3 has valueif (var3)std::cout << "var3 has value\n"; // var3 has valuestd::cout << "var2: " << var2.value() << ", var3: " << var3.value() << "\n"; // var2: China, var3: Haidianvar2.swap(var3);std::cout << "var2: " << var2.value() << ", var3: " << var3.value() << "\n"; // var2: Haidian, var3: Chinaif (var2 != var3)std::cout << "var2 != var3\n"; // var2 != var3return 0;
}

      执行结果如下图所示:

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

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

npm 下载包失败解决方案

1.【问题描述】使用 npm 下载vue项目依赖包时失败&#xff0c;版本不一致。 【解决方法】使用 npm install --force npm install --force 是一个命令行指令&#xff0c;用于在 Node.js 环境中使用 npm&#xff08;Node Package Manager&#xff09;安装包或模块。–force 参数表…

RK3568平台 查看内存的基本命令

一.free命令 free命令显示系统使用和空闲的内存情况&#xff0c;包括物理内存、交互区内存(swap)和内核缓冲区内存。共享内存将被忽略。 Mem 行(第二行)是内存的使用情况。 Swap 行(第三行)是交换空间的使用情况。 total 列显示系统总的可用物理内存和交换空间大小。 used 列显…

开发知识点-Ant-Design-Vue

Ant-Design-Vue a-input a-input Vue组件 a-spin 加载中的效果 data字段 mounted钩子函数 Ant Design Vue 组件库 list-type“picture-card” 上传的图片作为卡片展示 name show-upload-list action :beforeUpload“handleBeforeUpload” :headers“customHeaders” :disabl…

Java自学第9课:JSP基础及内置对象

目录&#xff1a; 目录 1 JSP基础知识架构 1 指令标识 1 Page命令 2 Including指令 3 taglib指令 2 脚本标识 1 JSP表达式 2 声明标识 3 代码片段 3 JSP注释 1 HTML注释 2 带有JSP表达式的注释 3 隐藏注释 4 动态注释 4 动作标识 1 包含文件标识 2 请求转发标…

包教包会:Mysql主从复制搭建

笑小枫的专属目录 一、无聊的理论知识1. 主从复制原理2. 主从复制的工作过程3. MySQL四种同步方式 二、docker下安装、启动mysql1. 安装主库2. 安装从库 三、配置Master(主)四、配置Slave(从)五、链接Master(主)和Slave(从)六、主从复制排错1. 错误&#xff1a;error connectin…

k8s-Pod控制器

一、Pod控制器 1.Pod控制器及其功用 Pod控制器&#xff0c;又称之为工作负载&#xff08;workload&#xff09;&#xff0c;是用于实现管理pod的中间层&#xff0c;确保pod资源符合预期的状态&#xff0c;pod的资源出现故障时&#xff0c;会尝试进行重启&#xff0c;当根据重启…

Ubuntu22.04 下 NFS 相关问题与完整配置(客户机 MacOS)

categories: [Linux-Shell] tags: Linux NFS 写在前面 最近折腾一下 NFS, 先白嫖一顿华子云的 1 个月服务器, 2C4G 感觉不错了, 但NFS 配置起来还是有点难度, 主要还是随机分配的端口配置方面比较恶心. server环境: 华为云 2C4G Ubuntu22.04 client环境: MacOS M1 with brew …

C语言——个位数为 6 且能被 3 整除但不能被 5 整除的三位自然数共有多少个,分别是哪些?

#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h> int main() {int i,j0;for(i100;i<1000;i) {if(i%106&&i%30&&i%5!0){printf("%6d",i); j;}}printf("\n一共%d个\n",j);return 0; } %6d起到美化输出格式的作用&#xff…

java 类和对象 (图文搭配,万字详解!!)

关于java类和对象&#xff0c;我们要掌握几个重点&#xff01; 1.类的定义方式以及对象的实例化 2.类中的成员变量和成员方法的使用 3.对象的整个初始化过程 4.封装特性 5.代码块 目录 一、面向对象的初步认识 1.1 什么是面向对象 1.2 面向对象与面向过程 1.2.1传统洗…

Vue 最简单路由 页面路由 配置路由

路由安装 Vue3使用 vue-router4 Vue2使用 vue-router3 npm i vue-router3创建路由文件 配置路由规则 import Vue from vue import VueRouter from vue-router //导入路由器 Vue.use(VueRouter)import Login from ../components/Login import User from ../components/User //…

tomcat+idea--如何在idea上发布项目

对应于idea2022以后的版本 &#xff08;一&#xff09;如何配置idea上的tomcat&#xff1f; 1、新建一个项目&#xff0c;左上角File&#xff0c;new&#xff0c;project&#xff0c;新建后就和普通的java项目一样。 2、然后点击项目名&#xff0c;右键选择“Add framework s…

运行npm install卡住不动的几种解决方案

在前端开发经常会遇到运行npm install 来安装工具包一直卡住不动&#xff0c;为此这里提供几种解决方案&#xff0c;供大家参考学习&#xff0c;不足之处还请指正。 第一种方案、首先检查npm代理&#xff0c;是否已经使用国内镜像 // 执行以下命令查看是否为国内镜像 npm con…