【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…

latex 中页边距和字体大小以及行间距怎么修改

在 LaTeX 中修改页边距、字体大小和行间距可以通过调整文档类选项或使用特定的宏包来实现。 以下是详细的方法&#xff1a; 修改页边距 使用 geometry 宏包&#xff1a; 这是最常用的方法&#xff0c;geometry 宏包允许你非常灵活地设置页面尺寸和边距。你可以通过在导言区&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;包括种植、采摘、加…

Python使用socket实现简易的http服务

在接触的一些项目中&#xff0c;有时为了方便可视化一些服务状态&#xff08;请求数很少&#xff09;&#xff0c;那么很容易想到使用http服务来实现。但开源的web后端框架&#xff0c;例如flask&#xff0c;fastapi&#xff0c;django等略显沉重&#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…

【JVM中的三色标记法是什么?】

JVM中的三色标记法是什么? 一、基本概念二、标记过程三、优势与问题四、漏标与多标的解决方案三色标记法(Tri-color Marking Algorithm)是Java虚拟机(JVM)中一种用于追踪对象存活状态的垃圾回收算法。 它基于William D. Hana和Mark S. McCulleghan在1976年提出的两色标记法…

【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.*")…

【0390】Postgres内核 启动 checkpointer process ( 1 )

文章目录 1. signal 间接启动1.1 signal callback 初始化1.2 处理 child process 各种退出状态1.3 start checkpointer process1. signal 间接启动 checkpointer process 的主要入口点是 CheckpointerMain(), 它是从 AuxiliaryProcessMain() 调用的,AuxiliaryProcessMain() …

《AI赋能鸿蒙Next,打造极致沉浸感游戏》

在游戏开发领域&#xff0c;鸿蒙Next系统与人工智能技术的结合为开发者们带来了前所未有的机遇&#xff0c;使打造更具沉浸感的游戏成为可能。以下将深入探讨如何利用人工智能在鸿蒙Next上开发出令人身临其境的游戏。 利用AI优化游戏角色智能行为 在传统游戏中&#xff0c;非…

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

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

C# 迭代,递归,回调--13

目录 一.迭代 迭代器示例: 关键点: 优势: 二.递归 递归示例: 关键点: 优势: 注意: 三.回调 回调示例: 关键点: 优势: 应用场景: 4.三种模式的特点对比: 迭代: 递归: 回调: 一.迭代 在C#中迭代通常指重复执行一系列指令 在C#中,迭代器是一种特殊的结构,允许…

炸砖块游戏的最终图案

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