*️⃣前言
在 C++17 中标准化了 std::optional
。该类型可以容纳一种类型,且判断是否有无。
若使用的标准在低于 C++17 则可以使用 Abseil 的 absl::optional
或 Boost 的 boost::optional
。
基础的使用方式在以前的文章中有介绍:(C++17) optional的使用 , 也可直接参照:std::optional 。
本文主要介绍3中optional的常用主流用法。
*️⃣3 种主流用法
1️⃣函数返回值
在一个函数想要同时获得结果,且判断是否有效时,在传统方式中通常有两种方式。
- 回参为值,入参为bool
int div_method_1(int numerator, int denominator, bool* ok);
- 回参为bool,入参为值
bool div_method_2(int numerator, int denominator, int* ret);
使用 std::optional
将结果和bool包成一个整体,作为返回值。
#include <iostream>
#include <optional>
std::optional<int> div_opt(int numerator, int denominator) {
if (0 == denominator) {
return std::nullopt;
}
return numerator / denominator;
}
void test(int x, int y) {
auto opt = div_opt(x, y);
if (opt.has_value()) {
std::cout << true << opt.value() << std::endl;
} else {
std::cout << false << opt.value_or(0) << std::endl;
}
}
int main() {
std::cout << std::boolalpha;
test(6, 2);
test(6, 0);
}
2️⃣函数参数
当我们要设计一个函数的时候,有的参数我们希望不传入,可以设置一个默认值。
但有一个情况,那就是当用户就是想要传入这个默认值来操作时,会影响函数的内部设计和外部使用者对函数作用的疑惑。
/**
* @param num 0表示无效值
*/
int square(int num = 0);
此时使用std::optional
就可以完美的解决这个问题。
#include <iostream>
#include <optional>
/**
* 非常明确,当 num 为空(std::nullopt) 就是外部未传值
*/
int square(std::optional<int> num = std::nullopt) {
if (num.has_value() == false) {
return -1;
}
return num.value() * num.value();
}
int main() {
std::cout << square() << std::endl; // -1
std::cout << square(114514) << std::endl; // 228554308
}
3️⃣类成员
当我们设计类的字段的时候,有时候希望能够将不同情况做一致的统一。
比如现在有两个机器人分别可以在二维平面和三维空间进行移动,这时明明有两个轴式可以复用的,但是我们还是要设计两种类型。
struct RobotCoordinate2 {
int x;
int y;
};
struct RobotCoordinate3 {
int x;
int y;
int z;
};
但使用了std::optional
就可以将z轴作为一个可选项了。
且一眼就能看出哪些字段是必备的,哪些是可选的。
#include <optional>
struct RobotCoordinate {
int x;
int y;
std::optional<int> z;
};
⭐END
🌟跋
ref:
《现代C++软件架构》
5.2.6 使用std::optional
p98
替换类型
cppref
🌟交流方式
⭐交流方式⭐ |C/C++|算法|设计模式|软件架构-优快云社区
关注我,学习更多C/C++,python,算法,软件工程,计算机知识
B站:
👨💻主页:天赐细莲 bilibili
![]()