std::variant是C++17引入的类型安全联合体,可存储多种类型之一并运行时明确当前类型;它通过内部索引和类型标签确保访问安全,支持std::get、std::holds_alternative和std::visit等操作。

std::variant 是 C++17 引入的类型安全联合体(type-safe union),它能在一个对象中存储多种不同类型中的某一种,同时在运行时明确知道当前存的是哪一种——彻底避免了传统 union 的类型擦除和未定义行为风险。
核心特点:比 union 更安全、比 void* 更清晰
传统 union 不记录当前活跃成员,读写错误类型会触发未定义行为;std::variant 内部自带“当前索引”(index)和类型标签,所有访问都受检查:
- 构造时自动记录所选类型
- 用
std::get<T>(v)或std::get<i>(v)访问前会做运行时校验(debug 模式下抛std::bad_variant_access) - 支持
std::holds_alternative<T>(v)判断是否持有某类型 - 支持
std::visit对不同情况统一处理,无需手动 switch index
基本用法:声明、构造、访问
假设你想表示一个可能为整数、浮点数或字符串的值:
#include <variant>
#include <string>
#include <iostream>
<p>using MyVariant = std::variant<int, double, std::string>;</p><p><span>立即学习</span>“<a href="https://pan.quark.cn/s/6e7abc4abb9f" style="text-decoration: underline !important; color: blue; font-weight: bolder;" rel="nofollow" target="_blank">C++免费学习笔记(深入)</a>”;</p><div class="aritcle_card flexRow">
<div class="artcardd flexRow">
<a class="aritcle_card_img" href="/ai/859" title="Tome"><img
src="https://img.php.cn/upload/ai_manual/000/000/000/175679992061586.jpg" alt="Tome" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a href="/ai/859" title="Tome">Tome</a>
<p>先进的AI智能PPT制作工具</p>
</div>
<a href="/ai/859" title="Tome" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a>
</div>
</div><p>MyVariant v1 = 42; // 自动推导为 int
MyVariant v2 = 3.14; // 推导为 double
MyVariant v3 = std::string{"hi"}; // 必须显式构造 string,否则会被当 const char*访问方式有三种常用形式:
-
std::get<int>(v1)—— 按类型取,失败抛异常 -
std::get<0>(v1)—— 按序号取(0=first type=int),同样带检查 -
std::holds_alternative<double>(v1)—— 先判断再取,避免异常
推荐写法:用 std::visit 处理多态逻辑
比起一堆 if (holds_alternative<...>),std::visit 更简洁、更不易漏分支:
std::visit([](const auto& x) {
using T = std::decay_t<decltype(x)>;
if constexpr (std::is_same_v<T, int>) {
std::cout << "int: " << x << '\n';
} else if constexpr (std::is_same_v<T, double>) {
std::cout << "double: " << x << '\n';
} else if constexpr (std::is_same_v<T, std::string>) {
std::cout << "string: " << x << '\n';
}
}, v1);也可以用重载的 lambda(C++17 起支持):
auto printer = [](const auto& x) {
std::cout << x << '\n';
};
std::visit(printer, v1); // 自动匹配对应类型的 operator()实用细节与注意事项
-
std::monostate可作为占位类型,让 variant 支持“空状态”,比如std::variant<std::monostate, int, std::string> - variant 不允许包含自身类型(如
std::variant<int, std::variant<...>>),但可通过std::unique_ptr间接实现递归结构 - 移动语义完整支持:move 构造/赋值后原对象处于有效但未指定状态(通常为第一个类型的默认值)
- 大小是各备选类型最大 size + 少量控制字节(一般 1–2 字节),比
std::any更轻量










