(C++17) optional的使用

在编程和实际项目中,数据可能出现不合法的情况,以往处理方式存在弊端。C++17推出std::optional来解决该问题,C++20和C++23还进行了加强。本文介绍了std::optional的简单示例、构造(空值、原位构造等)及访问(取值、逻辑判断)等使用方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

⭐前言与需求

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 *> opt
    std::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

🌟关注我

关注我,学习更多C/C++,算法,计算机知识

B站:

👨‍💻主页:天赐细莲 bilibili

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天赐细莲

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值