【C++】optional的使用(一)

这篇文章介绍下C++17引入的std::optional

为什么要有 optional

一般来说,如果想要一个函数返回“多个”值,C++程序员倾向于使用结构体/类完成这个操作。即定义一个通用的结构体,在函数内部完成装填,然后返回一个实例化的结构体。

#include <iostream>using namespace std;struct Out {string out1 { "" };string out2 { "" };
};pair<bool, Out> func(const string& in) {Out o;if (in.size() == 0)return { false, o };o.out1 = "hello";o.out2 = "world";return { true, o };
}int main() {if (auto [status, o] = func("hi"); status) {cout << o.out1 << endl;cout << o.out2 << endl;}return 0;
}

(代码来自 https://zhuanlan.zhihu.com/p/64985296)

C++17引入了std::optional,介绍如下:

The class template std::optional manages an optional contained value,
i.e. a value that may or may not be present. A common use case for
optional is the return value of a function that may fail. As opposed
to other approaches, such as std::pair<T,bool>, optional handles
expensive-to-construct objects well and is more readable, as the
intent is expressed explicitly. 类模板 std::optional
管理一个可选的容纳值,即可以存在也可以不存在的值。 一种常见的 optional 使用情况是一个可能失败的函数的返回值。与其他手段,如
std::pair<T,bool> 相比, optional 良好地处理构造开销高昂的对象,并更加可读,因为它显式表达意图。

换句话说,一个普通的变量,只有不同的值。而optional相当于在外面套了一层壳,先考虑存不存在值,再考虑值是多少。

使用

对于像我这样的菜鸟来说,optional 的源代码十分复杂的。但是使用起来并不困难,理解上面的含义就行。

  /*** @brief Class template for optional values.*/template<typename _Tp>class optional: private _Optional_base<_Tp>,private _Enable_copy_move<// Copy constructor.is_copy_constructible_v<_Tp>,// Copy assignment.__and_v<is_copy_constructible<_Tp>, is_copy_assignable<_Tp>>,// Move constructor.is_move_constructible_v<_Tp>,// Move assignment.__and_v<is_move_constructible<_Tp>, is_move_assignable<_Tp>>,// Unique tag type.

可以看到,本质上其实是个模板类,将包裹的类型以模板参数T的方式传入。

初始化

optional几种初始化如下:

    //初始化为空optional<int> int_empty;//使用有效值初始化(C++其他初始化方法也同样可用)optional<int> my_int = 2;//使用make_optionalauto doubleOpt = std::make_optional(10.0);auto complexOpt = std::make_optional<std::complex<double>>(3.0, 4.0);//使用in_placeoptional<vector<int>> vectorOpt{in_place, {1, 2, 3}};//使用其它optional对象复制/移动构造auto optCopied = vectorOpt;

说一下第三点和第四点,就是这个std::make_optionalstd::in_place。我搜到的资料显示这代表直接调用模板T的构造函数,即“完美转发”。

假设我有这么一个类 TestOp:

struct TestOp
{TestOp() : age(100) {}int getAge() { return age; }private:int age;
};

它有一个无参数的构造函数,但这个构造函数为成员赋默认值。这时,若使用如下写法

    optional<TestOp> test_op;cout << test_op.value().getAge() << endl;

会编译失败。因为optional并不会调用TestOp的默认构造函数,只会创建一个空的TestOp对象。
编译失败
这让我非常不理解,因为就算是未传入参数,应该调用T的默认构造函数才对。
你可能想到,如果初始化时直接传入构造函数呢?

    optional<TestOp> test_op{TestOp()};

这样写当然没问题,我们将得到包含默认TestOp对象的optional对象。但是在上面的代码中,将先构造出一个TestOp的临时对象,然后调用move函数将这个临时对象“移动”到optional存储的对象中,带来了额外的开销。在这种情况下,我们就只能使用std::in_place/ std::make_optional来“原地”构造optional底层存储的对象。

另一种情况是,TestOp禁用了移动构造和复制构造函数,这时候也只能用std::in_place/ std::make_optional

最后一种必须使用std::in_place/ std::make_optional的情况是,当你需要使用多个参数初始化同一个变量时,比如std::vector。没错,原生的 optional构造函数,并不支持多参数,神奇吧?
6
我猜想多参数的支持会导致歧义。

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

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

相关文章

fckeditor编辑器改造示例:增加PRE,CODE控件

查看专栏目录 Network 灰鸽宝典专栏主要关注服务器的配置&#xff0c;前后端开发环境的配置&#xff0c;编辑器的配置&#xff0c;网络服务的配置&#xff0c;网络命令的应用与配置&#xff0c;windows常见问题的解决等。 文章目录 修改方法&#xff1a;1&#xff09;修改fckco…

Python项目——贪吃蛇

1、原理 整个界面由一个二维数组组成。游戏开始时&#xff0c;会随机生成一个苹果&#xff08;红点&#xff09;和一条蛇&#xff08;黄点&#xff09;。蛇会在二维数组中移动&#xff0c;当蛇碰到苹果时&#xff0c;苹果被吃&#xff0c;蛇的长度加一&#xff08;红点变黄点&…

性能测试

什么是性能测试&#xff1f;性能测试定义性能测试和功能测试区别性能测试常见术语及指标1&#xff1a;用户数3&#xff1a;响应时间4&#xff1a;事务5&#xff1a;每秒事务通过数6&#xff1a;用户点击率7&#xff1a;吞吐量8&#xff1a;吞吐率9&#xff1a;思考时间10&#…

C++函数返回值类型不确定处理办法-函数重载

如果有一个函数的返回值不确定是int还是float&#xff0c;比如&#xff1a; int func(const int& input) {return(input 1);} float func(const int& input) {return(input 1);} //重定义报错float a func(1); 这样定义肯定是会报错的。因为同名函数的重载只能用…

基于ssm的简单学校课程管理系统的设计与实现(源码+调试)

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。今天给大家介绍一篇基于ssm的简单学校课程管…

【Python测试开发】文件上传操作

先写一个上传页面 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>文件上传</title><link href"http://dcn.bootcss/bootstrap/3.3.0/css/bootstrap.min.css" rel"styleshee…

探索Nginx的奥秘--从代理到负载均衡的艺术实践

文章目录 &#x1f33a;Nginx的引入&#x1f33a;&#x1f33a;深刻理解正向代理与反向代理&#x1f33a;&#x1f339;Reverse proxy&#x1f339;&#x1f339;正向代理与反向代理的区别&#x1f339;&#x1f339;反向代理为什么叫反向代理&#x1f339;&#x1f339;负载均…

C#教程(三):字符串的各种用法

在C#中&#xff0c;字符串&#xff08;string 类型&#xff09;是一种常用的数据类型&#xff0c;用于存储和操作文本数据。以下是一些C#中字符串的常见用法 1、输出任意的字符串长度 代码 #region 输出任意的字符串长度 Console.WriteLine("请输入你心中想到的名字&…

Activiti工作流框架学习笔记(一)之通用数据表详细介绍

文/朱季谦 Activiti工作流引擎自带了一套数据库表&#xff0c;这里面有一个需要注意的地方&#xff1a; 低于5.6.4的MySQL版本不支持时间戳或毫秒级的日期。更糟糕的是&#xff0c;某些版本在尝试创建此类列时将引发异常&#xff0c;而其他版本则不会。执行自动创建/升级时&a…

C++ 二叉搜索树(BST)的实现(非递归版本与递归版本)与应用

C 二叉搜索树的实现与应用 一.二叉搜索树的特点二.我们要实现的大致框架三.Insert四.InOrder和Find1.InOrder2.Find 五.Erase六.Find,Insert,Erase的递归版本1.FindR2.InsertR3.EraseR 七.析构,拷贝构造,赋值运算符重载1.析构2.拷贝构造3.赋值运算重载 八.Key模型完整代码九.二…

html css概念

1. 理解基本概念 HTML5&#xff1a;HTML&#xff08;HyperText Markup Language&#xff09;是网页的骨架。HTML5 是最新版本&#xff0c;提供了更多的标签和API&#xff0c;用于更丰富的网页功能和更好的用户体验。CSS3&#xff1a;CSS&#xff08;Cascading Style Sheets&am…

2020年第九届数学建模国际赛小美赛D题石头剪刀游戏与合作解题全过程文档及程序

2020年第九届数学建模国际赛小美赛 D题 石头剪刀游戏与合作 原题再现&#xff1a; 小时候你可能至少玩过几次石头剪刀游戏。在这个游戏中&#xff0c;你几乎有三个选择&#xff0c;每一个都有一个项目要打败&#xff0c;一个项目输给。石头打败剪刀&#xff0c;剪刀剪纸和布覆…

yasaf永安视安防监控恢复案例

永安视(yasaf)一个小到连官网都没有的安防厂商&#xff0c;是国内众多品牌中的一个&#xff0c;可以说是小十八线&#xff0c;让人敬佩的是这么一个小厂也自行写了嵌入式方案&#xff0c;下边我们来看看这个恢复案例。 故障存储: WD500G 故障现象: 此安防设备在使用过程中被…

Nougat:结合光学神经网络,引领学术PDF文档的智能解析、挖掘学术论文PDF的价值

Nougat&#xff1a;结合光学神经网络&#xff0c;引领学术PDF文档的智能解析、挖掘学术论文PDF的价值 这是Nougat的官方存储库&#xff0c;Nougat是一种学术文档PDF解析器&#xff0c;可以理解LaTeX数学和表格。 Project page: https://facebookresearch.github.io/nougat/ …

python/c++ Leetcode题解——1.两数之和

目录 方法1:枚举法 思路 Code 方法2:哈希表 思路 Code 方法1:枚举法 思路 最容易想到的方法是枚举数组中的每一个数 x&#xff0c;寻找数组中是否存在 target - x。 当我们使用遍历整个数组的方式寻找 target - x 时&#xff0c;需要注意到每一个位于 x 之前的元素都已…

Bash批处理文件:清理磁盘缓存

代码&#xff1a; echo offset SYSTEMDRIVE%systemdrive% set WINDIR%windir% set USERPROFILE%userprofile%echo 正在进行深度清理&#xff0c;请稍候......:: 清理临时文件夹 echo 删除 %temp% 文件夹中的所有文件... if exist "%temp%\*" (del /f /s /q %temp%\*…

Java-抽象类详解

目录 1、抽象类基本概念 2、抽象类语法 3、抽象类特性 4、抽象类和普通类之间的关系 1、抽象类基本概念 在面向对象的概念中&#xff0c;所有的对象都是通过类来描绘的&#xff0c;但是反过来&#xff0c;并不是所有的类都是用来描绘对象的&#xff0c;如果一个类中没有包含…

【机器学习】应用KNN实现鸢尾花种类预测

目录 前言 一、K最近邻&#xff08;KNN&#xff09;介绍 二、鸢尾花数据集介绍 三、鸢尾花数据集可视化 四、鸢尾花数据分析 总结 &#x1f308;嗨&#xff01;我是Filotimo__&#x1f308;。很高兴与大家相识&#xff0c;希望我的博客能对你有所帮助。 &#x1f4a1;本文由Fil…

07-抽象工厂

意图 提供一个创建一系列相关或相互依赖对象的接口&#xff0c;而无需指定它们具体的类。 适用性 在以下的情况可以选择使用抽象工厂模式&#xff1a; 一个系统要独立于它的产品的创建、组合和表示。一个系统要由多个产品系列中的一个来配置。要强调一系列相关的产品对象的…

【华为机试】2023年真题B卷(python)-堆栈中的剩余数字

一、题目 题目描述&#xff1a; 向一个空栈中依次存入正整数&#xff0c; 假设入栈元素 n(1<n<2^31-1)按顺序依次为 nx…n4、 n3、n2、 n1, 每当元素入栈时&#xff0c;如果 n1n2…ny(y 的范围[2,x]&#xff0c;1<x<1000)&#xff0c;则 n1~ny 全部元素出栈&#x…