C++那些事之玩转optional

news/2024/11/26 1:51:23/

C++那些事之玩转optional

  • C++那些事之玩转optional

  • 0.导语

  • 1.引入

  • 2.简易版optional

  • 3.指针版optional

  • 4.pair版optional

  • 5.storage版optional

  • 6.union版optional

  • 7.小项目:字符串转数字

0.导语

本节将会引入5个版本的optional实现,最终揭秘C++ STL optional实现,最后给出一个小项目作为练习的例子,让大家感受step by step学习的乐趣,所有代码、答案与相关参考资料,已更新于知识星球,欢迎大家加入学习。

73d473246e32bd66e145da817574159f.png

e3fc1512f80fc1b2191b034880ee4d88.jpeg

1.引入

C++17之后,C++标准库提供了std::optional,它是一个管理可选包含值的类模板。可选类型或有时也称为Maybe类型表示可选值的封装。

The class template std::optional manages an optional contained value, i.e. a value that may or may not be present.

cppreference:

https://en.cppreference.com/w/cpp/utility/optional

那么在C++17之前自己实现的话,如何造一个std::optional?

2.简易版optional

第一个版本是比较简单的,我们引入bool变量来标记当前类模版是否办函值。

template <typename T>
class Optional {
private:bool hasValue;T value;
};

在使用的地方:

if (optionalInt.hasValue()) {
} else {
}

仔细想想这样子写有什么问题呢?

  1. 内存对齐开销,增加了bool+padding的开销。

  2. 构造T对象的开销,例如:T无效时,是没有必要的。

那么如何优化呢?

3.指针版optional

template <typename T>
class Optional {
private:std::unique_ptr<T> value;
};

调用处:

if (val) {// has value
} else {// nullptr
}

这个虽然解决了上述的问题,却引发了下面几个问题:

  1. 内存开销:std::unique_ptr使用了堆内存来存储实际值。这意味着每个可选类型对象都需要额外的堆内存分配,这可能会导致内存开销增加。

  2. 不能存储空值:std::unique_ptr要求始终持有一个有效的指针,因此无法表示空值。如果你需要表示一个可选类型的空值状态,你可能需要引入其他的标志来表示空值状态。

对于第二点,给个示例,当直接获取数据是,此时应该预期返回空值,而不是nullptr。

// 报错:空指针
std::cout << "Value: " << optionalInt.getData() << std::endl;

4.pair版optional

对于前面几个版本都有点问题,继续优化,我们不用unique_ptr,回到第一个版本,干掉bool变量不就解决了一开始的内存对齐问题吗。

template <typename T>
class Optional {
private:T data;
};

在返回数据的时候带上bool标记不就行了。

std::pair<bool, T> getData() const {if (con) {return std::make_pair(true, data);} else {return std::make_pair(false, data);}
}

调用的时候我们通过first、second这种方式语义太不明确了,接口不够清晰。

otherOptionalInt.getData().first 
otherOptionalInt.getData().second

5.storage版optional

我们希望可选对象默认情况下不构造包含的对象。实现它的一种方法是使用std::aligned_storage为所包含的对象保留空间,随后用placement new,即使用new运算符在现有位置构造一个对象。

template <typename T>
class Optional {private:using StorageType =typename std::aligned_storage<sizeof(T), alignof(T)>::type;StorageType data;bool hasValue;
};

6.union版optional

在C++ stl中实现为:

struct _Empty_byte { };
union _Storage
{_Empty_byte _M_empty;_Up _M_value;
};

使用处:

_Storage<_Stored_type> _M_payload;

我们对这个做一层抽象,变为了当前的union版本实现:

struct _Empty_byte { };template <typename T>
class Optional {
private:union {T value;_Empty_byte empty;};bool hasValue;
}

这下跟stl实现差不多了,缺了一些继承/封装等等。

7.小项目:字符串转数字

给大家布置一个课堂练习,壳子为,请补充完代码。

inline std::string trim(const std::string& s)
{}
template<typename T = int>
std::optional<T> stonum(const std::string& st)
{}// 调用
int main()
{string num;num = "n1";if (auto n = stonum(num); n.has_value())cout << num << " is integer " << *n << endl;elsecout << num << " is not an integer" << endl;num = "42z";if (auto n = stonum(num); n.has_value())cout << num << " is integer " << *n << endl;elsecout << num << " is not an integer" << endl;
}

本节抽丝剥茧,一层层的揭开optional的实现,欢迎大家转发支持。


http://www.ppmy.cn/news/699585.html

相关文章

abap GUI_DOWNLOAD 可下载Excel TXT的文档

今天给大家分享一个函数,可以用来下载Excel和TXT格式的文件,非常好用 所需的变量: DATA:lv_filename TYPE string,lv_path TYPE string,lv_fullpath TYPE string,lv_destination LIKE rlgrap-filename,ls_objdata LIKE wwwdatatab,lv_objid TYPE wwwda…

《东周列国志》第八十一回 美人计吴宫宠西施 言语科子贡说列国

话说越王勾践欲访求境内美女&#xff0c;献于吴王&#xff0c;文种献计曰&#xff1a;“愿得王之近竖百人&#xff0c;杂以善相人者&#xff0c;使挟其术&#xff0c;遍游国中&#xff0c;得有色者&#xff0c;而记其人地&#xff0c;于中选择&#xff0c;何患无人。”勾践从其…

Java开发的第一个开源项目

在如鹏网上听网上课程&#xff0c;发现自己不能做代码工作&#xff0c;应该自己动手写写开源项目给其他需要的人用。 jianfan4j.jar 主要实现了简繁体中文之间的转换 算法&#xff1a;利用HashMap存储简繁字典。然后遍历传入的数组&#xff0c;找到相应的键值。 package com.…

0505.Net基础班第十一天(面向对象继承)

1、里氏转换 1)、子类可以赋值给父类 2)、如果父类中装的是子类对象&#xff0c;那么可以讲这个父类强转为子类对象。 2、 子类对象可以调用父类中的成员&#xff0c;但是父类对象永远都只能调用自己的成员。 3、 is&#xff1a;表示类型转换&#xff0c;如果能够转换成功&…

用python随机获取中文名字

一直没找到好用的中文姓名库&#xff0c;暂且收集了下面这些姓名集合&#xff0c;可以随机选取&#xff0c;样本不多&#xff0c;但随机组合成三字姓名后&#xff0c;还是一个很大的数量级。 import randomdef get_one_name():XING [赵, 钱, 孙, 李, 周, 吴, 郑, 王, 冯, 陈,…

Python百行代码随机生成姓名

# -*- coding: utf-8 -*- # Author : hanfei # Time : 2022/4/30 11:26 # File : CreateChineseName.py # Project : python_api_ui_framework import randomxing [赵, 钱, 孙, 李, 周, 吴, 郑, 王, 冯, 陈, 褚, 卫, 蒋, 沈, 韩, 杨, 朱, 秦, 尤, 许,何, 吕, 施, 张, 孔…

随机取中文名字,百家姓,2500个常见字,支持复姓

随机取中文名字&#xff0c;百家姓&#xff0c;2500个常见字&#xff0c;支持复姓 /*** * Title: randomName * Description: 随机取名字* param simple 是否单姓* param len 生成姓名长度* return String 名字* author Tyrone.Li*/public static String randomName(boolean si…

C# 随机中文名

2.0版本 using System; using System.Collections.Generic; using Random System.Random; public class ChineseName {struct Vector2{public float x;public float y;public Vector2(float x, float y){this.x x;this.y y;}}/// <summary>/// 得到姓/// </summar…