std::optional通过类型安全方式解决空指针和魔术值问题,明确表示值可能不存在;std::variant则提供类型安全的联合体,用于持有多种预定义类型之一的值,二者均提升代码清晰度与健壮性。

在C++中,
std::optional
std::variant
std::optional
std::variant
std::optional<T>
T
nullptr
#include <optional>
#include <string>
#include <iostream>
std::optional<std::string> findUserById(int id) {
if (id == 123) {
return "Alice"; // 用户存在
}
return std::nullopt; // 用户不存在
}
// 使用示例
void optional_example() {
auto user1 = findUserById(123);
if (user1.has_value()) { // 检查是否有值
std::cout << "Found user: " << *user1 << std::endl; // 解引用获取值
} else {
std::cout << "User not found." << std::endl;
}
auto user2 = findUserById(456);
std::cout << "User 2: " << user2.value_or("Guest") << std::endl; // 提供默认值
}std::variant<Types...>
#include <variant>
#include <string>
#include <iostream>
// 定义一个可以是 int、double 或 string 的类型
using Value = std::variant<int, double, std::string>;
void processValue(const Value& val) {
// 使用 std::visit 进行模式匹配,处理不同类型
std::visit([](auto&& arg) {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, int>) {
std::cout << "Processing an int: " << arg << std::endl;
} else if constexpr (std::is_same_v<T, double>) {
std::cout << "Processing a double: " << arg << std::endl;
} else if constexpr (std::is_same_v<T, std::string>) {
std::cout << "Processing a string: " << arg << std::endl;
}
}, val);
}
// 另一种访问方式:std::get_if
void processValueGetIf(const Value& val) {
if (const int* pInt = std::get_if<int>(&val)) {
std::cout << "It's an int: " << *pInt << std::endl;
} else if (const std::string* pStr = std::get_if<std::string>(&val)) {
std::cout << "It's a string: " << *pStr << std::endl;
} else {
std::cout << "It's something else (maybe double)." << std::endl;
}
}
// 使用示例
void variant_example() {
Value v1 = 10;
processValue(v1);
Value v2 = 3.14;
processValue(v2);
Value v3 = "Hello Variant";
processValue(v3);
processValueGetIf(v1);
processValueGetIf(v3);
}
int main() {
optional_example();
std::cout << "\n--- Variant Examples ---\n";
variant_example();
return 0;
}在我看来,
std::optional
立即学习“C++免费学习笔记(深入)”;
首先,它终结了空指针(Null Pointer)的噩梦。在
optional
T*
std::shared_ptr<T>
if (ptr != nullptr)
nullptr
std::optional
其次,它杜绝了魔术值(Magic Values)的滥用。我们都曾为了表示“没有值”而绞尽脑汁:用
-1
""
0
int
-1
std::optional
T
再者,它让函数签名更加清晰,意图表达更明确。当一个函数返回
std::optional<T>
T
T
bool try_get(T& out_value)
对我个人而言,在许多旧项目中,我曾不得不编写大量的
if (ptr)
if (value == MAGIC_NUMBER)
std::optional
and_then
transform
std::variant
首先,与传统联合体(union)相比,
std::variant
union
std::variant
std::get
std::get_if
std::visit
std::variant
union
其次,与多态(polymorphism)相比,
std::variant
std::variant
std::variant
std::visit
那么,何时选择它们呢?
std::variant
std::variant
std::variant
std::visit
draw()
我的个人经验是,在一个早期设计阶段,我曾在一个协议解析项目中,面对多种消息结构,最初倾向于为每种消息定义一个基类和多个派生类,然后通过
dynamic_cast
std::variant
std::visit
在实际项目中,高效地运用
std::optional
std::variant
对于 std::optional
std::optional
std::optional<T>
nullptr
std::optional<User> findUser(int id); // 函数签名直接表达了意图
std::optional<T>
nullptr
optional
bool
bool
std::optional<bool>
std::optional<std::optional<T>>
*optional_value
optional_value.value()
std::bad_optional_access
optional_value.has_value()
optional_value.value_or(default_value)
and_then
transform
optional
// 更好的解包方式
if (auto user = findUser(123)) {
std::cout << "User name: " << *user << std::endl;
} else {
std::cout << "User not found." << std::cout;
}对于 std::variant
std::variant
std::variant
std::variant
std::visit
std::visit
std::variant
variant
// 配合 std::visit 的例子
struct MyVisitor {
void operator()(int i) const { std::cout << "It's an int: " << i << std::endl; }
void operator()(double d) const { std::cout << "It's a double: " << d << std::endl; }
void operator()(const std::string& s) const { std::cout << "It's a string: " << s << std::endl; }
};
std::visit(MyVisitor{}, someVariant);std::variant
variant
std::unique_ptr<T>
std::shared_ptr<T>
variant
std::variant<std::unique_ptr<TypeA>, std::unique_ptr<TypeB>>
std::variant
我个人在开发一个小型编译器时,深切体会到
std::variant
std::variant<Expr, Stmt, Decl>
std::visit
std::visit
std::visit
switch
以上就是C++如何使用std::optional和std::variant处理可选值的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号