std::variant 是 C++17 引入的类型安全联合体,可存储多种类型之一,需通过 std::get、std::holds_alternative 或 std::visit 安全访问,常用于替代传统 union 和处理多类型数据。

在C++17中引入的 std::variant 是一种类型安全的“联合体”(union),可以保存多种不同类型中的某一种值,但同一时间只能存储其中一种类型。它解决了传统 union 的类型不安全问题,是处理多类型变量的一种现代、安全且高效的方式。
什么是 std::variant?
std::variant 属于 std 命名空间,定义在
#include
#include iostream>
例如:
std::variantv = 42; // 存 int
v = "hello"; // 存 string
v = 3.14; // 存 double
每次赋值都会替换当前存储的值和类型。
立即学习“C++免费学习笔记(深入)”;
如何访问 variant 中的值?
由于 variant 可能包含多种类型,直接获取值是不安全的。C++ 提供了几种方式来安全地提取内容:
-
std::get
(v) :通过类型获取值,如果当前不是该类型会抛出 std::bad_variant_access 异常。 -
std::get
(v) :通过类型在 variant 列表中的索引获取(从0开始)。 -
std::holds_alternative
(v) :检查当前是否存储的是指定类型,返回 bool。
示例:
std::variantif (std::holds_alternative<:string>(v)) {
std::cout (v) } else {
std::cout (v) }
使用 visit 访问 variant(推荐方式)
更强大和类型安全的方式是使用 std::visit,它可以对 variant 中的实际值应用一个可调用对象(如 lambda),自动匹配类型。
例如,定义一个打印 variant 内容的 visitor:
std::visit([](const auto& value) {std::cout }, v);
如果你有多个 variant,std::visit 还支持同时访问多个 variant 的当前值。
复杂一点的例子:
std::variantstd::visit([](const auto& val) {
if constexpr (std::is_same_v
std::cout } else if constexpr (std::is_same_v
std::cout } else {
std::cout }
}, v);
常见用途与注意事项
适用场景:
- 替代不安全的 union
- 解析可能包含不同类型的数据(如 JSON 值)
- 函数返回多种类型之一(配合 std::monostate 实现可选状态)
- 事件处理系统中传递不同类型的事件数据
注意点:
- variant 默认构造时会用第一个可默认构造的类型进行初始化。如果第一个类型不能默认构造,需要显式初始化。
- 访问错误类型会抛异常(除非用 visit 或先判断)。
- 性能上略高于指针或继承方案,无堆分配开销。
- 不能存引用、数组或 void 类型。
基本上就这些。std::variant 让你在保持类型安全的同时灵活处理多种数据类型,是现代 C++ 中处理“可能是这个,也可能是那个”的理想工具。不复杂但容易忽略细节,建议结合 std::visit 和 std::holds_alternative 使用更安全。











