0

0

C++中的std::variant是什么?(如何替代类型不安全的union)

裘德小鎮的故事

裘德小鎮的故事

发布时间:2026-02-12 16:07:02

|

444人浏览过

|

来源于php中文网

原创

std::variant 是类型安全的“多选一”容器,编译期确定可存类型,访问需显式处理每种可能;它比 union 安全但略重,c++17 起支持,应优先用 std::visit 安全读取,配合 std::optional 可表达“可能为空”,且需确保所含类型移动操作为 noexcept。

c++中的std::variant是什么?(如何替代类型不安全的union)

std::variant 是什么,为什么不能直接用 union

它是一个类型安全的“多选一”容器,编译期就确定能存哪些类型,访问时必须显式处理每种可能——不像 union 那样允许你随便读一个未写入的成员,一读就未定义行为。

常见错误现象:union 里写了 int,却去读 float 字段,程序可能跑得“好像没问题”,但其实随时崩溃或返回垃圾值;std::variant 强制你用 std::visitstd::get 前先确认当前存的是谁。

  • 使用场景:需要在单个变量里动态切换几种固定类型(比如配置项可能是 intstd::stringbool
  • 性能影响:比裸 union 略重一点——多 1–2 字节存 type index,访问时有分支开销,但现代 CPU 分支预测很准,实际几乎不可测
  • 兼容性:C++17 起支持,MSVC 15.3+、GCC 7.0+、Clang 4.0+ 都行

怎么安全地读取 std::variant 的值

不能像 union 那样直接点字段;必须用 std::get(指定类型)或 std::visit(穷举所有可能)。

容易踩的坑:std::get<int>(v)</int>v 实际存的是 std::string 时会抛 std::bad_variant_access 异常——这反而是好事,总比静默读错强。

立即学习C++免费学习笔记(深入)”;

LanguagePro
LanguagePro

LanguagePro是一款强大的AI写作助手,可以帮助你更好、更快、更有效地写作。

下载
  • 推荐优先用 std::visit,尤其类型多于 2 个时,避免一堆 if (holds_alternative<...>)</...>
  • std::get<t></t> 适合你 100% 确定当前类型(比如刚用 std::holds_alternative<t></t> 检查过)
  • 别用 std::get_if<t></t> 后不检查返回指针是否为 nullptr——这是空指针解引用高发区

示例:

std::variant<int, std::string> v = "hello";
std::visit([](auto&& x) {
    using T = std::decay_t<decltype(x)>;
    if constexpr (std::is_same_v<T, int>) {
        std::cout << "int: " << x;
    } else if constexpr (std::is_same_v<T, std::string>) {
        std::cout << "string: " << x;
    }
}, v);

std::variant 和 std::optional 组合用的典型模式

很多真实场景不是“非此即彼”,而是“可能是 A、B、C,也可能啥都没有”——这时别硬塞一个“空类型”进去,直接套一层 std::optional<:variant b c>></:variant> 更清晰。

常见错误现象:有人定义 std::variant<a b c std::monostate></a> 来模拟“空”,结果每次访问前都要多写一次 std::holds_alternative<:monostate></:monostate>,逻辑噪音大。

  • std::optional<:variant>></:variant>has_value() 直观表达“有没有值”
  • 嵌套后访问略麻烦,建议封装成小函数,比如 get_if_int(const auto& optv)
  • 注意:std::variant 本身不允许含多个相同类型(std::variant<int int></int> 编译失败),但 std::optional<int></int>int 可以共存

移动语义和异常安全性要注意什么

std::variant 默认构造、赋值、交换都满足强异常安全(要么全成功,要么不变),但前提是它包含的所有类型也都满足——如果你塞了个可能抛异常的移动构造函数进去,整个 variant 的赋值就可能中途失败。

容易被忽略的地方:自定义类型放进 std::variant 前,务必确认它的移动操作是否 noexcept。否则 std::variant 的某些操作(比如 swap)会退化为拷贝+析构,性能掉一截。

  • 检查方式:看类型是否有 T(T&&) noexcept 构造函数
  • 如果类型不满足,又不想改它,可以用 std::unique_ptr<t></t> 包一层,移动变成本质上的指针复制
  • 别依赖 std::variant 自动帮你做深拷贝——它只管自己那块内存,内部类型的资源管理还是你自己负责
事情说清了就结束。最常出问题的不是语法,是忘了 variant 当前到底存了谁,以及没处理好自定义类型的移动异常边界。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

708

2023.08.02

css中float用法
css中float用法

css中float属性允许元素脱离文档流并沿其父元素边缘排列,用于创建并排列、对齐文本图像、浮动菜单边栏和重叠元素。想了解更多float的相关内容,可以阅读本专题下面的文章。

584

2024.04.28

C++中int、float和double的区别
C++中int、float和double的区别

本专题整合了c++中int和double的区别,阅读专题下面的文章了解更多详细内容。

104

2025.10.23

if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

806

2023.08.22

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

542

2023.09.20

c语言union的用法
c语言union的用法

c语言union的用法是一种特殊的数据类型,它允许在相同的内存位置存储不同的数据类型,union的使用可以帮助我们节省内存空间,并且可以方便地在不同的数据类型之间进行转换。使用union时需要注意对应的成员是有效的,并且只能同时访问一个成员。本专题为大家提供union相关的文章、下载、课程内容,供大家免费下载体验。

128

2023.09.27

c语言union的用法
c语言union的用法

c语言union的用法是一种特殊的数据类型,它允许在相同的内存位置存储不同的数据类型,union的使用可以帮助我们节省内存空间,并且可以方便地在不同的数据类型之间进行转换。使用union时需要注意对应的成员是有效的,并且只能同时访问一个成员。本专题为大家提供union相关的文章、下载、课程内容,供大家免费下载体验。

128

2023.09.27

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

708

2023.08.02

c语言 数据类型
c语言 数据类型

本专题整合了c语言数据类型相关内容,阅读专题下面的文章了解更多详细内容。

4

2026.02.12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 9.3万人学习

C 教程
C 教程

共75课时 | 4.7万人学习

C++教程
C++教程

共115课时 | 17.4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号