【C++】:浅析 std::optional

std::optional 是 C++17 引入的一个标准库特性,提供了一种简单的方式来表示一个可能存在或不存在的值。它可以用于替代指针或其他机制,以更安全和更清晰的方式处理可选值。

1. 基本概念

std::optional<T> 是一个模板类,其中 T 是存储的值的类型。std::optional 可以包含一个值,或者不包含值(即为空)。这使得它非常适合用于函数返回值,表示函数可能成功返回一个值,也可能失败。

2. 主要特性

  • 构造和赋值: 可以通过默认构造函数创建一个空的 std::optional,也可以通过值构造来创建一个包含值的 std::optional
  • 检查值的存在性: 使用 has_value() 或者布尔上下文来检查 std::optional 是否包含值。
  • 访问值: 使用 value() 方法获取值,如果没有值则抛出异常。可以使用 value_or(default_value) 方法提供一个默认值。
  • 重置: 使用 reset() 方法可以清空 std::optional 中的值。

3. 示例代码

以下是一个使用 std::optional 的示例:

#include <iostream>
#include <optional>
#include <string>std::optional<int> findValue(const std::string& key) {if (key == "valid") {return 42; // 返回一个有效值}return std::nullopt; // 返回空值
}int main() {// 使用 std::optionalstd::optional<int> result = findValue("valid");if (result.has_value()) {std::cout << "Found value: " << result.value() << std::endl;} else {std::cout << "Value not found." << std::endl;}// 使用默认值int value = findValue("invalid").value_or(0);std::cout << "Value: " << value << std::endl; // 输出: Value: 0return 0;
}

4. 代码说明

4.1. 函数 findValue:

  • 该函数接受一个字符串参数 key,如果 key"valid",则返回一个包含值 42std::optional<int>。如果 key 是其他值,则返回一个空的 std::optional

4.2. 主函数:

  • 调用 findValue 函数并检查返回的 std::optional 是否包含值。
  • 使用 value_or(0) 方法获取值,如果没有值则返回 0

5. 使用场景

  • 函数返回值: 当函数可能返回一个有效值或失败时,使用 std::optional 可以清晰地表示这一点。
  • 配置和参数: 在需要可选参数的情况下,使用 std::optional 可以使代码更具可读性。
  • 避免指针: 使用 std::optional 可以避免使用裸指针来表示可选值,从而减少潜在的空指针异常。

6. 注意事项

  • 性能: std::optional 的开销通常很小,但在某些情况下(如存储大型对象时),可能会影响性能。使用时要考虑到这一点。
  • 异常安全: 使用 value() 方法时,如果 std::optional 为空,将抛出 std::bad_optional_access 异常。使用 value_or() 可以避免这种情况。

7、基于C++11实现一个简单的optional类

#include <iostream>
#include <stdexcept>
#include <type_traits>template <typename T>
class Optional {
public:// 默认构造函数,初始化为空Optional() : hasValue(false) {}// 值构造函数Optional(const T& value) : hasValue(true) {new (&storage) T(value); // Placement new}// 移动构造函数Optional(T&& value) : hasValue(true) {new (&storage) T(std::move(value)); // Placement new}// 拷贝构造函数Optional(const Optional& other) : hasValue(other.hasValue) {if (hasValue) {new (&storage) T(*reinterpret_cast<const T*>(&other.storage));}}// 移动赋值运算符Optional& operator=(Optional&& other) {if (this != &other) {reset(); // 清空当前值hasValue = other.hasValue;if (hasValue) {new (&storage) T(std::move(*reinterpret_cast<T*>(&other.storage)));}}return *this;}// 拷贝赋值运算符Optional& operator=(const Optional& other) {if (this != &other) {reset(); // 清空当前值hasValue = other.hasValue;if (hasValue) {new (&storage) T(*reinterpret_cast<const T*>(&other.storage));}}return *this;}// 析构函数~Optional() {reset();}// 检查是否有值bool has_value() const {return hasValue;}// 获取值T& value() {if (!hasValue) {throw std::runtime_error("No value present");}return *reinterpret_cast<T*>(&storage);}const T& value() const {if (!hasValue) {throw std::runtime_error("No value present");}return *reinterpret_cast<const T*>(&storage);}// 获取值或默认值T value_or(const T& defaultValue) const {return hasValue ? value() : defaultValue;}// 重置值void reset() {if (hasValue) {reinterpret_cast<T*>(&storage)->~T(); // 调用析构函数hasValue = false;}}private:alignas(T) char storage[sizeof(T)]; // 存储值的内存bool hasValue; // 是否有值
};

使用示例:

// 示例使用
int main() {Optional<int> opt1; // 默认构造,空Optional<int> opt2(42); // 有值if (opt1.has_value()) {std::cout << "opt1 has value: " << opt1.value() << std::endl;} else {std::cout << "opt1 is empty." << std::endl;}if (opt2.has_value()) {std::cout << "opt2 has value: " << opt2.value() << std::endl;}// 使用 value_orstd::cout << "opt1 value or default: " << opt1.value_or(0) << std::endl; // 输出默认值 0return 0;
}

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

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

相关文章

图形和动画本地化

图形和动画本地化是多媒体改编的一个关键方面&#xff0c;需要对技术技能和文化细微差别有深入的理解。当由母语人士和设计师进行时&#xff0c;这一过程达到了自动化系统通常无法复制的真实性和相关性水平。 本土专业人士对文化偏好、象征主义和视觉美学有着固有的理解&#…

浅谈云计算06 | 云管理系统架构

云管理系统架构 一、云管理系统架构&#xff08;一&#xff09;远程管理系统&#xff08;二&#xff09;资源管理系统&#xff08;三&#xff09;SLA 管理系统&#xff08;四&#xff09;计费管理系统 二、安全与可靠性保障&#xff08;一&#xff09;数据安全防线&#xff08;…

SpringBoot 基础学习

对于SpringBoot的了解&#xff0c;在初学者的角度看来&#xff0c;它是一种工具&#xff0c;用于简化一个Spring项目的初始搭建和开发过程。 1 入门案例 1.1 项目的创建 有四种方法创建&#xff0c;可以通过idea快捷创建&#xff0c;Spring的官网创建&#xff0c;阿里云创建&am…

基于springboot+vue的洪涝灾害应急信息管理系统设计与实现

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

QTreeWidget QTreeWidgetItem

QTreeWidgetItem 是 Qt 框架中用于在 QTreeWidget 中表示树形结构中每个节点的类。它是 QTreeWidget 的一部分&#xff0c;允许您创建和管理层次结构的数据展示。 QTreeWidgetItem 用于表示树形结构中的单个节点。 添加子节点&#xff1a; 可以通过 addChild() 方法向节点添加…

基于springboot果蔬供应链信息管理平台

基于Spring Boot的果蔬供应链信息管理平台是一种集成了先进信息技术和果蔬供应链管理理念的综合性系统。 一、背景与意义 随着人们生活水平的提高和对健康饮食的重视&#xff0c;果蔬市场需求不断增长。然而&#xff0c;果蔬供应链涉及多个环节&#xff0c;包括种植、采摘、加…

25/1/13 嵌入式笔记 继续学习Esp32

PWM&#xff08;Pulse Width Modulation&#xff0c;脉宽调制&#xff09; 是一种通过快速切换高低电平来模拟中间电压值的技术。它广泛应用于控制 LED 亮度、电机速度、音频生成等场景。 analogWrite函数:用于在微控制器&#xff08;如 Arduino&#xff09;上生成模拟信号。 …

jupyter notebook练手项目:线性回归——学习时间与成绩的关系

线性回归——学习时间与学习成绩的关系 第1步&#xff1a;导入工具库 pandas——数据分析库&#xff0c;提供了数据结构&#xff08;如DataFrame和Series&#xff09;和数据操作方法&#xff0c;方便对数据集进行读取、清洗、转换等操作。 matplotlib——绘图库&#xff0c;p…

如何规模化实现完全自动驾驶?Mobileye提出解题“新”思路

在CES 2025上&#xff0c;Mobileye展示了端到端自动驾驶系统Mobileye Drive™&#xff0c;通过高度集成的传感器、算法和计算平台&#xff0c;可以实现自动驾驶功能的全覆盖。 Mobileye创始人兼首席执行官Amnon Shashua教授 期间&#xff0c;Mobileye创始人兼首席执行官Amnon …

Windows下安装和配置Go开发环境

文章目录 1. 介绍了SDK2. 下载 SDK工具包3. windows 下配置 Golang 环境变量 1. 介绍了SDK SDK 的全称(Software Development Kit 软件开发工具包)SDK是提供给开发人员使用的&#xff0c;其中包含了对应开发语言的工具包 2. 下载 SDK工具包 Go语言的官网为&#xff1a;https…

【javascript】Web APIs-Dom获取属性操作

目录 Web APIs-Dom获取&属性操作 Web API 基本认知 变量声明 建议&#xff1a; const 优先&#xff0c;尽量使用const&#xff0c;原因是&#xff1a; 1.1 作用和分类 1.2 什么是DOM 1.3 DOM树 1.4 DOM对象&#xff08;重要&#xff09; 2. 获取DOM对象 2.1 根据C…

新版AndroidStudio通过系统快捷创建带BottomNavigationView的项目踩坑记录

选择上面这个玩意创建的项目 坑点1 &#xff1a;配置的写法和不一样了 镜像的写法&#xff1a; 新的settings.gradle.kts中配置镜像的代码&#xff1a; pluginManagement {repositories {mavenCentral()google {content {includeGroupByRegex("com\\.android.*")…

SAP资产盘盈盘亏的过账处理、入账价值错误调整、资产减值准备

文章目录 一、SAP资产盘盈盘亏处理1、ABNAN盘盈 &#xff08;往年资产&#xff09; ABZON (当年资产&#xff09;2、ABAVN盘亏 二、资产价值入账错了&#xff08;价值多了或少了&#xff09;&#xff0c;怎么调账1、价值少了2、价值多了 三、资产减值准备1、启用重估2、指定间隔…

炸砖块游戏的最终图案

描述 小红正在玩一个“炸砖块”游戏,游戏的规则如下:初始有一个 n * m 的砖块矩阵。小红会炸 k 次,每次会向一个位置投炸弹,如果这个位置有一个砖块,则砖块消失,上方的砖块向下落。小红希望你画出最终砖块的图案。 输入描述 第一行输入三个正整数 n, m, k,代表矩阵的行…

【Python项目】图像信息隐藏技术的实现

【Python项目】图像信息隐藏技术的实现 技术简介&#xff1a;采用Python技术、MYSQL数据库等实现。 系统简介&#xff1a;系统主要的功能有登录模块、对个人信息的维护模块、图片信息的隐藏模块涉及图片的上传和信息的验证。 背景&#xff1a; 在当今时代&#xff0c;信息技术…

游戏市场成果及趋势

2024 年的游戏行业发展情况如何&#xff1f;这是一个既关系到开发商&#xff0c;又关系到玩家的问题&#xff0c;而市场分析师可以为我们揭晓答案。下面&#xff0c;就让我们来看看分析师给出的结论以及他们对未来趋势的预测。 玩家 自 2021 年起&#xff0c;全球平均游戏时间…

【算法学习】——整数划分问题详解(动态规划)

&#x1f9ee;整数划分问题是一个较为常见的算法题&#xff0c;很多问题从整数划分这里出发&#xff0c;进行包装&#xff0c;形成新的题目&#xff0c;所以完全理解整数划分的解决思路对于之后的进一步学习算法是很有帮助的。 「整数划分」通常使用「动态规划」解决&#xff0…

深入理解计算机系统阅读笔记-第十二章

第12章 网络编程 12.1 客户端-服务器编程模型 每个网络应用都是基于客户端-服务器模型的。根据这个模型&#xff0c;一个应用时由一个服务器进程和一个或者多个客户端进程组成。服务器管理某种资源&#xff0c;并且通过操作这种资源来为它的客户端提供某种服务。例如&#xf…

Redis 实战篇 ——《黑马点评》(中)

《引言》 &#xff08;中&#xff09;篇将接着记录 Redis 实战篇 ——《黑马点评》&#xff08;上&#xff09;篇之后的学习内容与笔记&#xff0c;希望大家能够点赞、收藏支持一下 ᕦ(&#xff65;ㅂ&#xff65;)ᕤ&#xff0c;谢谢大家。 传送门&#xff08;上&#xff09;&…

【2024年华为OD机试】(A卷,100分)- 猜字谜(Java JS PythonC/C++)

一、问题描述 小王设计了一个简单的猜字谜游戏&#xff0c;游戏的谜面是一个错误的单词&#xff0c;比如 nesw&#xff0c;玩家需要猜出谜底库中正确的单词。猜中的要求如下&#xff1a; 对于某个谜面和谜底单词&#xff0c;满足下面任一条件都表示猜中&#xff1a; 变换顺序…