Skip to content

std::variant(C++17)

一句话

一个类型安全的 union 替代品,能在同一块内存中存放不同类型的值,并通过索引或类型安全地访问。

头文件

#include <variant>

核心 API 速查

操作签名说明
构造函数variant()默认构造,持有第一个候选类型的值
赋值variant& operator=(T&& t)赋值并切换到对应类型
按类型访问template<class T> T& get(variant& v)按类型取值,类型不匹配时抛出异常
按索引访问template<size_t I> T& get(variant& v)按索引取值,索引越界时抛出异常
安全访问template<class T> T* get_if(variant* v)按类型取指针,不匹配时返回 nullptr
类型检查template<class T> bool holds_alternative(const variant& v)检查当前是否持有指定类型
访问器template<class Vis> R visit(Vis&& vis, variant& v)传入可调用对象,自动分发到当前活跃类型
当前索引size_t index() const返回当前活跃类型的零基索引
原位构造template<class T, class... Args> T& emplace(Args&&... args)销毁旧值并原位构造新值

最小示例

cpp
#include <iostream>
#include <string>
#include <variant>
// Standard: C++17
int main() {
    std::variant<int, std::string> v = 42;
    std::cout << std::get<int>(v) << '\n';
    v = "hello";
    std::cout << std::get<std::string>(v) << '\n';
    std::visit([](auto&& arg) {
        std::cout << arg << '\n';
    }, v);
}

嵌入式适用性:中

  • 相比裸 union,隐含了额外的类型索引存储和运行时检查开销
  • 避免了手动管理 union 脏标志位的出错风险,提升代码健壮性
  • 适合资源较充足(如带 MMU 的 SoC)的应用层状态管理或消息解析
  • 极度受限的裸机环境建议评估 sizeof 开销后谨慎使用

编译器支持

GCCClangMSVC
7.15.019.10

另见


部分内容参考自 cppreference.com,采用 CC-BY-SA 4.0 许可

基于 VitePress 构建