std::variant 安全替代裸 union:自带类型信息、自动调用构造/析构函数、访问时类型不匹配抛 std::bad_variant_access 异常,避免未定义行为。
在 C++ 中直接使用 union 是危险的:它不跟踪当前存储的类型,不自动调用构造/析构函数,容易引发未定义行为(UB)。C++17 引入的 std::variant 正是为安全替代裸 union 而设计——它自带类型信息、自动管理生命周期、提供访问保护。
传统 union 仅共享内存,不记录哪
个成员被初始化:
str 但刚写了 i)std::string)时,手动管理构造/析构极易出错std::variant 是类型安全的“可变容器”,内部维护当前索引和活跃值:
std::get(v) 或 std::visit 访问,若类型不匹配则抛 std::bad_variant_access
std::holds_alternative(v) 运行时类型查询假设原意表示“整数或字符串”:
// ❌ 危险的 union(尤其含 std::string)
union BadValue {
int i;
std::string s; // 非平凡类型 —— 构造/析构必须手动处理!
};
BadValue v;
new(&v.s) std::string("hello"); // 手动构造
v.s.~basic_string(); // 必须手动析构 —— 漏掉就泄漏
✅ 安全等价写法:
#include#include using Value = std::variant Value v = 42; // 自动调用 int 构造 v = std::string{"hi"}; // 自动析构 int、构造 string std::visit([](const auto& x) { using T = std::decay_t ; if constexpr (std::is_same_v ) std::cout << "int: " << x; else if constexpr (std::is_same_v ) std::cout << "string: " << x; }, v);
std::visit 替代 std::get:避免硬编码类型索引,更易维护std::optional<:variant>> 或加入 std::monostate
std::variant 的隐式转换(如 variant v = 3.14; 可能歧义),必要时用 std::in_place_type
v.index() 或 v.valueless_by_exception() 检查状态