C++(25): C++17探索:std::optional

1. 概述

std::optional是C++17标准引入的一个新的标准库组件。这是一个轻量级的容器,旨在以类型安全的方式包装可能为空的值。std::optional为处理可能缺失的数据提供了一种优雅而简洁的方法,这在以往通常需要使用专门的"存在"标志或复杂的错误处理机制。

简单点讲,std::optional在使用上并不复杂,主要用来替代那些需要返回NULL,或以返回-1表示错误等的场合。这样做最直观的一个改进就是易读性增强了。

2. 为什么需要std::optional?

在C++中,函数通常返回一个值或者在失败时返回一个特殊值(如NULL或-1)。这种方法存在几个问题:

(1)类型不安全:返回特殊值通常意味着函数返回的类型与实际返回值的类型不一致,这可能导致类型安全问题。

(2)语义不明确:使用特殊值来表示错误状态可能会与合法的返回值冲突。

(3)错误处理复杂:调用者需要检查返回的特殊值,并进行额外的错误处理。

std::optional提供了一种更好的解决方案,它允许函数明确地表达它们可能不返回有效值的情况。

3. std::optional的基本概念

std::optional<T>是一个模板类,其中T是被包装的值的类型。它包含以下两个主要状态:

无值状态:表示不包含有效的T类型对象。

有值状态:包含一个有效的T类型对象。

4. 使用std::optional

(1)构造

cpp 复制代码
std::optional<int> opt;         // 默认构造,无值状态

std::optional<int> opt(10);     // 有值状态,包含值10

(2)有无值判断has_value()

返回一个布尔类型,如果当前容器是有值状态,返回true,否则返回false。

使用方法如下:

cpp 复制代码
if (opt.has_value()) {

    // opt包含一个值

}

需要注意的是,当我们想要访问std::optional类型的值时,需要先判断是否有值,否则会出现未定义行为。

(3)使用operator*或value()访问存储的值

首先我们需要判断是否有值,然后再进行访问。

或者添加异常捕获单元。

cpp 复制代码
#include <optional>

#include <iostream>


int main(int argc, char* argv[])

{

    std::optional<int> opt(10);

    if (opt) {

        std::cout << "Value: " << *opt << std::endl; ///< 输出 10

    }

    return 0;

}

cpp 复制代码
int main(int argc, char* argv[])

{

    std::optional<int> opt;


    try {

        int value = opt.value(); ///< 这里会抛出异常

    } catch (const std::bad_optional_access& e) {

        std::cerr << "Exception: " << e.what() << std::endl;

    }

    return 0;

}

(4)value_or(T default):返回存储的值,如果std::optional处于无值状态,则返回提供的默认值。

cpp 复制代码
int value = opt.value_or(-1);  ///< 返回10,如果opt无值则返回-1

(5)reset():将std::optional重置为无值状态。

cpp 复制代码
opt.reset();  ///< opt变为无值状态

(6)emplace():在原地构造一个新值,如果std::optional已经有值,则先销毁旧值。

cpp 复制代码
opt.emplace(20);  // opt现在包含20
相关推荐
小欣加油7 小时前
leetcode2161 根据给定数字划分数组
数据结构·c++·算法·leetcode·职场和发展
吃着火锅x唱着歌7 小时前
深度探索C++对象模型 学习笔记 第五章 构造、解构、拷贝语意学(2)
c++·笔记·学习
玖釉-7 小时前
Vulkan 离屏渲染详解:从 Framebuffer 到后处理、阴影贴图与 Render Texture
c++·windows·计算机视觉·图形渲染
cpp_25017 小时前
P2947 [USACO09MAR] Look Up S
数据结构·c++·算法·题解·单调栈·洛谷
楼田莉子7 小时前
C++20新特性:协程
开发语言·c++·后端·学习·c++20
炘爚7 小时前
phase1:基础框架——编译 + MySQL + 登录/注册
linux·c++
特种加菲猫8 小时前
C++11核心特性深度解析:从列表初始化到lambda与包装器
开发语言·c++
枕星而眠8 小时前
C++ 面向对象核心机制深度解析:多态性、虚函数、虚继承与 final 类
运维·开发语言·c++·后端
智者知已应修善业8 小时前
【51单片机8个LED,已经使用了D1D2,怎么样在不动D1D2的前提下实现D6~D8的流水灯】2024-1-19
c++·经验分享·笔记·算法·51单片机
坚果派·白晓明8 小时前
鸿蒙PC适配实战:simdjson 三方库移植攻略与 AtomCode Skills 提效之道
c++·harmonyos·三方库·skills·atomcode·c/c++三方库·c/c++三方库适配