参考:https://blog.csdn.net/fengbingchun/article/details/134353178
int test_optional_init()
{
std::optional<int> var;
if (!var.has_value())
std::cout << "var is not set\n"; // var is not set
var = 8; // error: *var = 8, 因为var采用默认初始化为空
if (var.has_value())
std::cout << "var is present: " << var.value() << "\n"; // var is present: 8
if (var)
std::cout << "var is present: " << *var << "\n"; // var is present: 8
std::optional<int> var2{ std::nullopt }; // 将var2初始化置于"empty"状态
if (!var2.has_value())
std::cout << "var2 is not set\n"; // var2 is not set
std::optional<std::string> var3{ "China" };
if (var3 > std::nullopt)
std::cout << "var3 > std::nullopt\n"; // var3 > std::nullopt
auto var4 = std::make_optional<std::vector<char*>>({ "China", "Beijing", "Haidian" });
for (const auto& v : *var4)
std::cout << " " << v; // China Beijing Haidian
std::cout << "\n";
// 内建类型可不需指明存储类型,deduction guide
std::optional var5{ 2 };
std::cout << "var5: " << var5.value() << "\n"; // var5: 2
std::optional var6{ std::string{"China"} };
std::cout << "var6: " << var6.value() << "\n"; // var6: China
return 0;
}
std::optional成员函数:
- 1.访问存储值:
- (1).var.value():返回引用;如果没有值,会抛出std::bad_optional_access异常;
- (2).*var:如果没有值,会crash(or undefined behavior),返回存储值的引用;应该只用于已经确定含有值的场景
- (3).var.value_or:返回值,注意与value()的区别;如果没有值,则获取备选值;
- (4).var->:返回存储值的指针,可访问内部值的成员;
- 2.emplace:赋予一个新值(in-place);如果在调用之前已经存储一个值,则通过调用其析构函数来销毁所存储的值;
- 3.reset:如果存储一个值,则销毁该值;否则,没有任何影响;
- 4.has_value:返回std::optional对象是否存有值;
- 5.operator bool():返回std::optional对象是否存有值;
- 6.swap:交换两个std::optional对象的值;
非成员函数:
- 比较std::optional对象:operator==, !=, <, <=, >, >=, <=>。比较std::optional对象时,"empty"值即std::nullopt比任何有值的std::optional对象都要小。 std::bad_optional_access:是一个异常类,直接派生自std::exception,用于处理在访问std::optional对象时发生的错误,当尝试访问一个没有存储值的std::optional对象时,会抛出std::bad_optional_access异常。
int test_optional_member_functions()
{
// 获取std::optional值: var.value(), *var, var.value_or, var->
std::optional<int> var{ 8 };
std::cout << "var: " << var.value() << ", " << *var << "\n"; // var: 8, 8
*var = 6; std::cout << "var: " << *var << "\n"; // var: 6
var = 8; std::cout << "var: " << *var << "\n"; // var: 8
*var = 10; std::cout << "var: " << var.value_or(66) << "\n"; // var: 10
var.reset(); std::cout << "var: " << var.value_or(66) << "\n"; // var: 66
std::optional<std::string> var2{ "China" };
std::cout << "var2: " << var2->data() << "\n"; // var2: China
var.reset(); // or: var = {};
try {
std::cout << "var: " << var.value() << "\n";
//std::cout << "var: " << *var << "\n"; // 直接crash掉
}
catch (const std::bad_optional_access& e) {
std::cout << "exception: " << e.what() << "\n"; // var: exception: Bad optional access
}
std::string str{ "Beijing" }; // 不要对常量变量使用std::move
std::optional<std::string> var3(std::move(str));
std::cout << "var3: " << var3.value() << ", str: " << str << "\n"; // var3: Beijing, str:
var3.emplace("Haidian");
std::cout << "var3: " << var3.value() << "\n"; // var3: Haidian
if (var3.has_value())
std::cout << "var3 has value\n"; // var3 has value
if (var3)
std::cout << "var3 has value\n"; // var3 has value
std::cout << "var2: " << var2.value() << ", var3: " << var3.value() << "\n"; // var2: China, var3: Haidian
var2.swap(var3);
std::cout << "var2: " << var2.value() << ", var3: " << var3.value() << "\n"; // var2: Haidian, var3: China
if (var2 != var3)
std::cout << "var2 != var3\n"; // var2 != var3
return 0;
}