
| ✨博客主页 | ||
|---|---|---|
| 何曾参静谧的博客 | ||
| 📌文章专栏 | ||
| 「C/C++」C/C++程序设计 | ||
| 📚全部专栏 | ||
| 「VS」Visual Studio | 「C/C++」C/C++程序设计 | 「UG/NX」BlockUI集合 |
| 「Win」Windows程序设计 | 「DSA」数据结构与算法 | 「UG/NX」NX二次开发 |
| 「QT」QT5程序设计 | 「File」数据文件格式 | 「PK」Parasolid函数说明 |
std::optional容器详解
1. 引用头文件
std::optional是C++17标准库引入的一个模板类,用于表示一个值可能存在也可能不存在。要使用std::optional,首先需要包含头文件<optional>。
#include <optional>
2. 注意事项
- 空值检查:在访问std::optional的值之前,必须检查它是否包含值,否则会导致未定义行为。
- 生命周期:std::optional的生命周期与它包含的值的生命周期一致,不能返回包含局部变量的std::optional。
- 线程安全:std::optional本身不提供线程同步机制,在多线程环境中使用时需要额外的同步措施。
3. 函数构造
std::optional的构造方式多样,包括默认构造、值构造和使用std::nullopt构造。
std::optional<int> opt1; // 默认构造,无值状态
std::optional<int> opt2(10); // 值构造,包含值10
std::optional<int> opt3 = std::nullopt; // 无值状态,相当于默认构造
4. 对象初始化
std::optional对象可以通过多种方式初始化,包括直接赋值、emplace构造等。
std::optional<int> opt4;
opt4 = 20; // 直接赋值
std::optional<std::string> opt5;
opt5.emplace("Hello, World!"); // 使用emplace构造值
5. 元素访问
访问std::optional的值可以使用*运算符或value()方法,但需要先检查是否有值。使用value_or()时可以指定值不存在返回的值。
std::optional<int> opt2 = 10;
if (opt2) {
std::cout << "Value: " << *opt2 << std::endl; // 输出10
}
std::optional<int> opt3;
try {
std::cout << "Value or default: " << opt3.value_or(-1) << std::endl; // 输出-1
} catch (const std::bad_optional_access& e) {
std::cerr << "Exception: " << e.what() << std::endl;
}
6. 迭代器
std::optional不是一个容器,而是一个可能包含单个值的包装器,因此它没有迭代器。
7. 容器
虽然std::optional本身不是一个容器,但它可以作为一个容器的一部分,例如std::vector<std::optional<T>>。
std::vector<std::optional<int>> vec = {1, std::nullopt, 3};
8. 修改器
std::optional提供了多种修改器,包括重新赋值、重置为无值状态、交换值等。
std::optional<int> opt6(10);
opt6 = 20; // 重新赋值
opt6.reset(); // 重置为无值状态
std::optional<int> opt7(30);
std::optional<int> opt8(40);
opt7.swap(opt8); // 交换值
9. 元素比较
std::optional支持相等性比较,两个std::optional对象只有在都为空或都持有相等的值时才相等。
std::optional<int> opt9(10);
std::optional<int> opt10(10);
std::optional<int> opt11;
if (opt9 == opt10) {
std::cout << "opt9 and opt10 are equal." << std::endl;
}
if (!opt9 || !opt11 || opt9 != opt11) {
std::cout << "opt9 and opt11 are not equal or one of them is empty." << std::endl;
}
10.元素判断
#include <iostream>
#include <optional>
int main() {
std::optional<int> opt1; // 默认构造的 std::optional 是空的
std::optional<int> opt2 = 42; // 包含一个值
if (opt1.has_value()) {
std::cout << "opt1 has a value: " << opt1.value() << std::endl;
} else {
std::cout << "opt1 is empty" << std::endl;
}
if (opt2.has_value()) {
std::cout << "opt2 has a value: " << opt2.value() << std::endl;
} else {
std::cout << "opt2 is empty" << std::endl;
}
return 0;
}
总结
std::optional是C++17引入的一个非常有用的工具,它提供了一种优雅的方式来表示可能存在,也可能不存在的值。它避免了使用特殊值(如NULL或-1)来表示“无值”状态所带来的类型不安全、语义不明确和错误处理复杂等问题。std::optional的使用场景广泛,包括但不限于函数返回值、配置项可能未设置时、缓存结果可能不存在时等。
应用场景
- 函数返回值:当函数可能不返回有效结果时,可以使用std::optional表示返回值是可选的。
- 配置项:在读取配置文件时,某些配置项可能未设置,可以使用std::optional来表示这些配置项的值。
- 缓存结果:在缓存系统中,某些查询结果可能不存在,可以使用std::optional来表示这些结果。
- 延迟初始化:在某些情况下,对象的初始化可能依赖于某些条件,可以使用std::optional来处理延迟初始化。
std::optional的引入使得C++的类型系统更加完善,代码更加清晰和易于维护。


1533

被折叠的 条评论
为什么被折叠?



