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

(C++17) optional的使用

文章目录

  • 前言与需求
  • 使用
    • 简单示例
    • 构造
      • 空值
      • std::in_place 原位构造
      • 推导指引
      • std::make_optional
    • 访问
      • 取值
      • 逻辑判断
  • END

前言与需求

optional 》adj.可选择的,选修的

在编程与实际项目中,可能会出现数据不合法的需求与状态。

在以往通常的使用中,通常会为每种数据类型定义一个值作为不合法的标志。比如int = -1, string = “str_invalid”等等。

这种方式有许多弊端:

  1. 编写时麻烦
  2. 这些不合法数据在有的场景下可能是有效的
  3. 团队协作时需要来回确认
  4. 等等

为了处理这种可能出现不合法的情况,C++17推出了std::opational<>来处理这个问题。

在C++20和C++23对此还进行了加强,但本文不对这些加强做过多演示。

使用

std::optional - cppreference.com

简单示例

该实例简洁明了,能够基本了解optional的使用大意。

注意在optional是空值时,如还需要取值则会出现异常

terminate called after throwing an instance of ‘std::bad_optional_access’
what(): bad optional access

#include <iostream>
#include <optional>
#include <string>std::optional<std::string> create_optional(bool flag) {if (flag) {return "pass option";} else {// {} 也可行// return {};return std::nullopt;}
}void test(bool flag) {auto opt = create_optional(flag);// 可以直接作为if判断if (opt) {// 两种取值方法std::cout << opt.value() << std::endl;std::cout << *opt << std::endl;// 可以修改opt.value() = "modify opt.value()";std::cout << opt.value_or("no data") << std::endl;} else {// terminate called after throwing an instance of// 'std::bad_optional_access'//  what():  bad optional access// std::cout << opt.value() << std::endl;std::cout << opt.value_or("no data") << std::endl;}
}int main() {test(true);test(false);
}

构造

空值

#include <iostream>
#include <optional>
#include <string>int main() {std::optional<std::string> op0;std::optional<std::string> op1 = {};std::optional<std::string> op2 = std::nullopt;
}

std::in_place 原位构造

原位构造。使用std::in_place可以直接使用构造函数了。

#include <iostream>
#include <optional>
#include <string>int main() {// 调用 std::string( initializer_list<CharT> ) 构造函数std::optional<std::string> opt1(std::in_place, {'a', 'b', 'c'});// 调用 std::string( size_type count, CharT ch ) 构造函数std::optional<std::string> opt2(std::in_place, 3, 'A');std::cout << opt1.value() << '\n' << opt2.value() << std::endl;
}

推导指引

都C++17了,推到指引必不可少

注意数组还是退化成 T*

#include <optional>
#include <string>int main() {int arr[2];// std::optional<int *> optstd::optional opt{arr};// class std::optional<const char *>std::optional str = "abc";using namespace std::literals;// class std::optional<std::string>std::optional str_i = "abc"s;
}

std::make_optional

用对应的make函数进行构造。

#include <iomanip>
#include <iostream>
#include <optional>
#include <string>
#include <vector>int main() {auto opt = std::make_optional<std::vector<int>>(5, 2);for (int i : *opt) {std::cout << i << " ";}std::cout << std::endl;std::string str{"hello world"};auto        opts = std::make_optional<std::string>(std::move(str));std::cout << std::quoted(opts.value_or("empty value"))<< std::endl;std::cout << str << std::endl;
}

访问

取值

直接使用operator*()或者value()即可

注意,考虑空值时需要套用上带默认值版本的value_or()

#include <iostream>
#include <optional>
#include <string>int main() {auto opt = std::make_optional<std::string>("Hello World");std::cout << opt.value() << std::endl;std::cout << *opt << std::endl;std::cout << opt.value_or("no data") << std::endl;// 都可以修改// opt.value() = "modify data";*opt = "modify data";if (opt.has_value()) {std::cout << opt.value_or("no data") << std::endl;}// 重置opt.reset();std::cout << opt.value_or("no data") << std::endl;// 异常// terminate called after throwing an instance of 'std::bad_optional_access'// what():  bad optional access// std::cout << opt.value() << std::endl;
}

逻辑判断

因为有operator bool()所以可以直接在if等逻辑判断中使用。

#include <iostream>
#include <optional>
#include <string>int main() {auto opt = std::make_optional<std::string>("Hello World");if (opt.has_value()) {std::cout << opt.value_or("no data") << std::endl;}if (opt) {std::cout << opt.value_or("no data") << std::endl;}
}



END

相关文章:

  • Presentation Prompter 5.4.2(mac屏幕提词器)
  • Ubuntu配置网络与静态IP地址的常见方法
  • MySQL数据库的各种锁介绍以及它们之间的关系
  • 图解三傻排序 选择排序、冒泡排序、插入排序
  • 微服务架构——笔记(3)Eureka
  • 293_C++_告警类
  • Visual Studio 2017附加依赖项
  • 商城系统分布式下单
  • 【Spring Boot 源码学习】JedisConnectionConfiguration 详解
  • 软磁直流测试系统电参量指标
  • 【论文阅读】Generating Radiology Reports via Memory-driven Transformer (EMNLP 2020)
  • 基于Skywalking的全链路跟踪实现
  • 电机应用-直流有刷电机
  • 1212. 地宫取宝
  • 【解决问题】---- 解决 avue-crud 表格勾选数据翻页后界面保持选中
  • @jsonView过滤属性
  • js面向对象
  • MaxCompute访问TableStore(OTS) 数据
  • mongo索引构建
  • STAR法则
  • Sublime Text 2/3 绑定Eclipse快捷键
  • Tornado学习笔记(1)
  • vue 配置sass、scss全局变量
  • vue2.0项目引入element-ui
  • vue2.0一起在懵逼的海洋里越陷越深(四)
  • 闭包--闭包作用之保存(一)
  • 分布式任务队列Celery
  • 工程优化暨babel升级小记
  • 基于 Ueditor 的现代化编辑器 Neditor 1.5.4 发布
  • 理解在java “”i=i++;”所发生的事情
  • 力扣(LeetCode)965
  • 聊聊flink的BlobWriter
  • 爬虫进阶 -- 神级程序员:让你的爬虫就像人类的用户行为!
  • 前端性能优化--懒加载和预加载
  • 算法系列——算法入门之递归分而治之思想的实现
  • hi-nginx-1.3.4编译安装
  • 阿里云IoT边缘计算助力企业零改造实现远程运维 ...
  • 阿里云移动端播放器高级功能介绍
  • 京东物流联手山西图灵打造智能供应链,让阅读更有趣 ...
  • ​低代码平台的核心价值与优势
  • #LLM入门|Prompt#1.7_文本拓展_Expanding
  • (173)FPGA约束:单周期时序分析或默认时序分析
  • (Oracle)SQL优化技巧(一):分页查询
  • (附源码)springboot优课在线教学系统 毕业设计 081251
  • (更新)A股上市公司华证ESG评级得分稳健性校验ESG得分年均值中位数(2009-2023年.12)
  • (蓝桥杯每日一题)love
  • (求助)用傲游上csdn博客时标签栏和网址栏一直显示袁萌 的头像
  • (新)网络工程师考点串讲与真题详解
  • (转)PlayerPrefs在Windows下存到哪里去了?
  • .locked1、locked勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .net core webapi 大文件上传到wwwroot文件夹
  • .NET 材料检测系统崩溃分析
  • .NET 服务 ServiceController
  • .net 开发怎么实现前后端分离_前后端分离:分离式开发和一体式发布
  • .NET/C# 使用反射调用含 ref 或 out 参数的方法