如何優雅處理多參數返回/無參數返回——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請訪問


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM