应优先用std::variant实现类型安全联合体,因其编译期限定类型、零成本访问;std::any适用于运行时未知类型的泛化场景,但有运行时开销和不安全转换。

std::any 和 std::variant 都不是“联合体”,但常被误称为类型安全联合体
它们根本不是 union 的替代品:std::any 可存任意类型(运行时擦除),std::variant 是编译期限定的类型列表(类似增强版 union)。真想用类型安全联合体,该用 std::variant;想存“不知道什么类型”的值,才选 std::any。
std::variant 要求编译期明确所有可能类型,std::any 不要求
std::variant 的类型集合必须在模板参数中写死,比如 std::variant。一旦定义,就不能塞入 bool 或 std::vector —— 编译直接报错。std::any 没这限制,任何可复制类型都能塞进去,但代价是:运行时类型检查、无访问优化、无法静态推导行为。
-
std::variant✅v = 42; -
v = std::string("hi");❌ 编译失败(std::string不在类型列表中) -
std::any a = 42; a = std::string("hi");✅ 全部合法
访问方式完全不同:variant 用 visit 或 get,any 用 any_cast
std::variant 访问必须处理所有可能分支(否则 std::visit 可能抛 std::bad_variant_access),而 std::any 的 any_cast 是不安全的 C 风格强制转换:类型不匹配就抛 std::bad_any_cast,且无法像 std::visit 那样做模式匹配。
std::variantv = "hello"; 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::any a = 3.14; double d = std::any_cast (a); // OK int i = std::any_cast (a); // 抛 std::bad_any_cast
性能和内存开销差异显著
std::variant 通常只比最大类型多几个字节(用于存储当前索引),访问是零成本抽象;std::any 至少含一个指针 + 类型信息,小对象也可能堆分配(取决于实现),每次 any_cast 都要运行时比较 type_info。
立即学习“C++免费学习笔记(深入)”;
- 对性能敏感、类型集合固定 → 优先用
std::variant - 需要泛化容器(如配置项、插件接口传参)、类型完全动态 → 才考虑
std::any - 二者都不该用来替代
union或void*做底层数据搬运
std::variant 非法),更不能直接序列化——这些边界条件往往在跨模块传递时突然暴露。









