std::variant 是类型安全的编译期确定联合体,不是多态机制;它在运行时仅存一种已知类型,通过 index() 或 holds_alternative() 跟踪活跃类型,适用于 JSON 解析等有限类型场景。
std::variant 是什么,不是什么
std::variant 不是多态机制,它不依赖虚函数表,也不要求类型间有继承关系。它本质是一个**类型安全的联合体(union)**,在编译期确定所有可能类型,运行时仅存其中一种,并用内部索引(index())或类型标签(holds_alternative())跟踪当前活跃类型。
它解决的问题很具体:需要一个变量能“在几个已知类型中选一个”并保证访问安全,比如解析 JSON 时字段可能是 int、double 或 std::string,但绝不会是用户自定义未声明的类型。
怎么正确构造和访问 variant
构造时必须明确初始化为某一个可选项,不能留空(除非含 std::monostate);访问必须通过 std::visit 或 std::get,且后者在类型不匹配时抛 std::bad_variant_access 异常。
- 推荐用
std::visit+ lambda 处理所有分支,避免手动检查index()或重复调用holds_alternative -
std::get(v)仅在 100% 确认当前是T时使用(例如刚用holds_alternative(v)检查过) - 若需默认行为,把
std::monostate放在 variant 列表首位,它代表“空状态”,可被默认构造
std::variant v = 42;
std::visit([](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 << "double: " << x;
} else {
std::cout << "string: " << x;
}
}, v);
为什么不能替代继承多态,以及它的代价在哪
std::variant 的类型集合在编译期固定,无法动态扩展;而继承多态靠运行时绑定,支持新子类无需修改已有容器逻辑。这是根本设计分歧,不是“哪个更好”,而是“是否适用”。
立即学习“C++免费学习笔记(深入)”;