如何优雅处理多参数返回/无参数返回——std::optional

Posted riko707

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何优雅处理多参数返回/无参数返回——std::optional相关的知识,希望对你有一定的参考价值。

什么是std::optional?

C++17中新引入了std::optional<T>。类模板std::optional管理一个可选的容纳值。简单说来,std::optional就是一个和类型,常见的用处就是作为函数返回值来处理一个可能失败的函数。

如何处理无参返回?

此前处理无参返回的函数一般有两种方式。

第一种:

bool foo(int param1, int*param2);

返回参数作为引用/指针型输入参数而存在,传入地址,在执行完毕后访问指定地址得到返回值,而使用真正的返回值来作为函数是否成功的返回。
这种方式可以实现需求。
缺点是:

  1. 浪费存储空间——无论是否返回值,都需要做好有值的准备,param2的空间需要事先分配
  2. 可读性/可用性差——同为参数,有的是输入参,有的是输出参,即使以名字取分,使用的时候也比较困难。

第二种:

std::pair<T,bool>foo(int param1);

这是比较常用的方式,解决了问题2——每次使用都知道返回值是pair的第一个值,第二个值专门用于成功与否的判断。
不过std::optional继续优化了处理方式。

正如前述,std::optional管理的是可选的容纳值。如果函数成功执行,则实例含值,如果执行失败,实例不含值。

如何处理多参返回?

这都不是个问题,classstruct,哪个都比直接放在一个tuple里面或者更过分的直接列在函数参数里面好。

使用std::optional

  • 定义位置:<optional>
  • T:一个满足可析构的类型
  • 初始化:
    • 使用=用另一个T类型含值std::optional初始化
    • 使用构造函数初始化:以nullopt_t类型值或是T类型值
    • 默认构造函数
  • 是否含值:
    • 使用bool hasValue=temp.has_value()检查是否含值
  • 取值:
    • 使用(*temp)T即默认为T的指针
    • 使用temp.value()获取T
    • 使用temp.value_or()获取值(存在值)或者其他(不存在值)
  • 返回:
    • 一个T对象(非指针)
    • nullopt
    • ...

一个实例:

//一个可析构类型
class Test
    int num1;
    int num2;
    Test(int n1,int n2)
        num1=n1;
        num2=n2;
    
    bool isOK()
        return num1+num2>=0?true:false;
    


//一个可能执行失败的函数【有点草率,看看语法就好
std::optional<Test>foo(int num)
    Test t(num,num);
    if(t.isOK())
        //返回正常对象
        return t;
    
    //返回空值
    return nullopt;


int main()
    int myAge=20;
    //一种赋值方式
    std::optional<Test>opt=foo(myAge);
    //一种判断是否含值的方式
    if(opt.has_value())
        //foo函数成功执行
        //一种取值方式
        cout<<(opt.value()).num1<<endl;
    

Reference

cppreference-std::optional 更多特性/支持的操作请访问
C++17 新特性之 std::optional(上)更好地理解为何使用std::optional请访问

以上是关于如何优雅处理多参数返回/无参数返回——std::optional的主要内容,如果未能解决你的问题,请参考以下文章

函数参数,返回值,递归函数

07_函数进阶

函数进阶

.NET Core统一参数校验异常处理结果返回功能实现

.NET Core统一参数校验异常处理结果返回功能实现

.NET Core统一参数校验异常处理结果返回功能实现