optional的使用"/>
(C++17) optional的使用
文章目录
- 前言与需求
- 使用
- 简单示例
- 构造
- 空值
- std::in_place 原位构造
- 推导指引
- std::make_optional
- 访问
- 取值
- 逻辑判断
- END
前言与需求
optional 》adj.可选择的,选修的
在编程与实际项目中,可能会出现数据不合法的需求与状态。
在以往通常的使用中,通常会为每种数据类型定义一个值作为不合法的标志。比如int = -1
, string = “str_invalid”
等等。
这种方式有许多弊端:
- 编写时麻烦
- 这些不合法数据在有的场景下可能是有效的
- 团队协作时需要来回确认
- 等等
为了处理这种可能出现不合法的情况,C++17推出了std::opational<>
来处理这个问题。
在C++20和C++23对此还进行了加强,但本文不对这些加强做过多演示。
使用
std::optional - cppreference
简单示例
该实例简洁明了,能够基本了解optional的使用大意。
注意在optional是空值时,如还需要取值则会出现异常
terminate called after throwing an instance of ‘std::bad_optional_access’
what(): bad optional access
#include <iostream>
#include <optional>
#include <string>std::optional<std::string> create_optional(bool flag) {if (flag) {return "pass option";} else {// {} 也可行// return {};return std::nullopt;}
}void test(bool flag) {auto opt = create_optional(flag);// 可以直接作为if判断if (opt) {// 两种取值方法std::cout << opt.value() << std::endl;std::cout << *opt << std::endl;// 可以修改opt.value() = "modify opt.value()";std::cout << opt.value_or("no data") << std::endl;} else {// terminate called after throwing an instance of// 'std::bad_optional_access'// what(): bad optional access// std::cout << opt.value() << std::endl;std::cout << opt.value_or("no data") << std::endl;}
}int main() {test(true);test(false);
}
构造
空值
#include <iostream>
#include <optional>
#include <string>int main() {std::optional<std::string> op0;std::optional<std::string> op1 = {};std::optional<std::string> op2 = std::nullopt;
}
std::in_place 原位构造
原位构造。使用std::in_place
可以直接使用构造函数了。
#include <iostream>
#include <optional>
#include <string>int main() {// 调用 std::string( initializer_list<CharT> ) 构造函数std::optional<std::string> opt1(std::in_place, {'a', 'b', 'c'});// 调用 std::string( size_type count, CharT ch ) 构造函数std::optional<std::string> opt2(std::in_place, 3, 'A');std::cout << opt1.value() << '\n' << opt2.value() << std::endl;
}
推导指引
都C++17了,推到指引必不可少
注意数组还是退化成 T*
#include <optional>
#include <string>int main() {int arr[2];// std::optional<int *> optstd::optional opt{arr};// class std::optional<const char *>std::optional str = "abc";using namespace std::literals;// class std::optional<std::string>std::optional str_i = "abc"s;
}
std::make_optional
用对应的make函数进行构造。
#include <iomanip>
#include <iostream>
#include <optional>
#include <string>
#include <vector>int main() {auto opt = std::make_optional<std::vector<int>>(5, 2);for (int i : *opt) {std::cout << i << " ";}std::cout << std::endl;std::string str{"hello world"};auto opts = std::make_optional<std::string>(std::move(str));std::cout << std::quoted(opts.value_or("empty value"))<< std::endl;std::cout << str << std::endl;
}
访问
取值
直接使用operator*()
或者value()
即可
注意,考虑空值时需要套用上带默认值版本的value_or()
#include <iostream>
#include <optional>
#include <string>int main() {auto opt = std::make_optional<std::string>("Hello World");std::cout << opt.value() << std::endl;std::cout << *opt << std::endl;std::cout << opt.value_or("no data") << std::endl;// 都可以修改// opt.value() = "modify data";*opt = "modify data";if (opt.has_value()) {std::cout << opt.value_or("no data") << std::endl;}// 重置opt.reset();std::cout << opt.value_or("no data") << std::endl;// 异常// terminate called after throwing an instance of 'std::bad_optional_access'// what(): bad optional access// std::cout << opt.value() << std::endl;
}
逻辑判断
因为有operator bool()
所以可以直接在if等逻辑判断中使用。
#include <iostream>
#include <optional>
#include <string>int main() {auto opt = std::make_optional<std::string>("Hello World");if (opt.has_value()) {std::cout << opt.value_or("no data") << std::endl;}if (opt) {std::cout << opt.value_or("no data") << std::endl;}
}
END
更多推荐
(C++17) optional的使用
发布评论