C++ 17 std::variant

C++ 17 std::variant
枫C++ 17 std::variant
std::variant是 C++17 提供的一个类型安全联合体(type-safe union)。它可以在多个类型中保存其中一个值,但和传统union不同的是,它知道自己当前存的是哪一种类型。
1. 为什么需要 std::variant?
以前如果一个变量可能是多种类型,常见做法一般有几种:
- 用
union - 用基类指针 + 多态
- 自己维护一个“类型标签 + 数据”的结构
这些方法都能解决问题,但要么不够安全,要么写起来比较重。std::variant 可以把“多种可能类型中的一种”这个需求直接表达出来。
2. 基本使用
2.1 定义 variant
1 |
|
这里 data 可以在 int、double、string 三种类型之间切换,但同一时刻只保存一种。
3. 访问值的方法
3.1 std::get
1 | std::variant<int, string> v = 42; |
如果当前存的不是这个类型,std::get 会抛异常。
3.2 std::get_if
更稳妥一点的做法是:
1 | if (auto p = std::get_if<int>(&v)) { |
如果类型不匹配,它会返回 nullptr。
3.3 index()
可以查看当前保存的是第几个候选类型:
1 | cout << v.index() << endl; |
4. std::visit
visit 是 std::variant 很重要的配套工具,用来根据当前实际类型执行不同逻辑。
1 |
|
这样就不用手动一层层判断当前类型了。
5. 一个实际一点的例子
1 |
|
像这种“配置值可能是多种类型”的场景,variant 就很合适。
6. 和 union 的区别
union
- 更底层
- 需要手动管理当前类型
- 对复杂类型支持不自然
variant
- 类型安全
- 知道当前保存的是哪种类型
- 可以直接存放
std::string这类复杂对象
7. 使用时要注意的点
7.1 std::get 可能抛异常
如果你不能确定当前类型,优先用 get_if 或 visit。
7.2 它不是“同时保存多个值”
variant<int, double> 不是同时有 int 和 double,而是当前只会有一种。
7.3 第一类型可能作为默认构造结果
很多时候默认构造的 variant 会持有第一个可默认构造的类型,这一点要心里有数。
总结
std::variant 很适合表达“一个值可能是几种类型中的一种”这类需求。
相比手写类型标签或传统 union,它更安全,也更现代。对于配置系统、表达式树、消息载荷、状态值这类场景,还是很值得掌握的。














