0

0

C++ std::any 与 std::variant 是什么?(如何替代传统的 void* 和 union)

裘德小鎮的故事

裘德小鎮的故事

发布时间:2026-02-12 16:03:14

|

823人浏览过

|

来源于php中文网

原创

std::any用于运行时未知类型的单值存储,依赖动态类型检查;std::variant适用于编译期已知有限类型的高效安全切换,需全覆盖处理。选any当类型完全不确定,选variant当类型集合固定且需高性能分发。

c++ std::any 与 std::variant 是什么?(如何替代传统的 void* 和 union)

std::any 能存任意类型,但取值前必须知道类型

它像一个带类型擦除的“万能盒子”,运行时才检查类型是否匹配。和 void* 不同,std::any 自带类型信息,不会让你在解引用时崩溃——但如果你猜错了类型,std::any_cast 会抛出 std::bad_any_cast 异常。

常见错误现象:std::any_cast<int>(a)</int> 对一个存了 doublestd::any 调用,直接崩溃(没捕获异常);或者用 std::any_cast<const int></const> 去取一个右值,编译失败。

  • 使用场景:配置项解析、插件系统中传递未知但单次确定的值(比如某个字段可能是 intstd::string,但具体哪种由 JSON 字段名决定)
  • 安全取值必须先用 std::any_cast<t>(&a)</t> 检查是否可转,或用 std::any_cast<t>(a)</t> 并包 try/catch
  • 性能影响:每次 std::any_cast 都要动态类型比对,比直接访问慢;内部可能堆分配(小对象优化取决于实现)
  • 别把它当 union 用——它不支持多类型共存,也不提供 switch-case 式的类型分发

std::variant 是编译期限定的“安全 union”

std::variant 在定义时就锁死了能存哪些类型,比如 std::variant<int std::string double></int>。它比原始 union 安全得多:构造、析构、赋值都自动管理活跃成员,不会出现“用 int 覆盖 string 后还调 string 析构函数”的 UB。

常见错误现象:忘记处理所有分支,std::visit 传入的 visitor 缺少对某个类型的重载,导致编译失败;或者用 std::get<t>(v)</t> 强制取值,而当前活跃类型不是 T,抛出 std::bad_variant_access

Qoder
Qoder

阿里巴巴推出的AI编程工具

下载

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

  • 使用场景:状态机返回值(成功/失败/超时)、AST 节点类型(BinaryOp/Literal/Identifier)、协议字段的多种可能取值
  • 必须用 std::visit 处理所有可能类型,推荐用 lambda 模板或 std::overload 辅助类组织逻辑
  • 参数差异:std::get_if<t>(&v)</t> 返回指针,安全但需判空;std::get<t>(v)</t> 更快但不安全,只应在确定类型后使用
  • 内存布局紧凑,无堆分配,访问开销接近原生 union,但多了 1–2 字节的 type index

什么时候选 any,什么时候选 variant?

关键看“类型集合”是编译期可知,还是运行时才确定。

  • std::any:你根本不知道将来会塞什么类型(比如用户脚本传进来的值),且只存不频繁切换
  • std::variant:你知道全部可能类型,且需要高效、无异常地分发处理(比如解析器每步只产出几种固定节点)
  • 别用 std::any 模拟枚举行为——类型太多会导致运行时检查膨胀,也难维护
  • 别用 std::variant 存 “任意类型”,比如 std::variant<:any ...></:any>,这等于放弃类型安全又没换来灵活性

替代 void* 和 union 的真实代价

它们确实消除了裸指针的悬垂风险和 union 的手动生命周期管理,但引入了新约束:类型必须明确、可比较、可拷贝(或移动)。尤其要注意 std::variant 中的类型不能是抽象类、数组或带删除拷贝构造的类型。

  • void* 的自由是以放弃所有类型检查为代价的;std::anystd::variant 把检查移到了更早阶段——一个在运行时,一个在编译时
  • 兼容性上,std::any 要求 C++17,std::variant 同样;老项目升级时注意 MSVC/GCC/Clang 版本是否支持完整特性(比如 Clang 5+ 才完全支持 std::variant 的 constexpr 构造)
  • 最容易被忽略的一点:std::variantstd::monostate 占位符不是摆设——它让 variant 可默认构造,否则所有类型都得有默认构造函数,这点在设计接口时经常卡住

热门AI工具

更多
DeepSeek
DeepSeek

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

豆包大模型
豆包大模型

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

通义千问
通义千问

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

腾讯元宝
腾讯元宝

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

文心一言
文心一言

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

讯飞写作
讯飞写作

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

即梦AI
即梦AI

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

ChatGPT
ChatGPT

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

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

436

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

544

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

317

2023.10.13

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

81

2025.09.10

string转int
string转int

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

708

2023.08.02

switch语句用法
switch语句用法

switch语句用法:1、Switch语句只能用于整数类型,枚举类型和String类型,不能用于浮点数类型和布尔类型;2、每个case语句后面必须跟着一个break语句,以防止执行其他case的代码块,没有break语句,将会继续执行下一个case的代码块;3、可以在一个case语句中匹配多个值,使用逗号分隔;4、Switch语句中的default代码块是可选的等等。

550

2023.09.21

Java switch的用法
Java switch的用法

Java中的switch语句用于根据不同的条件执行不同的代码块。想了解更多switch的相关内容,可以阅读本专题下面的文章。

432

2024.03.13

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

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

128

2023.09.27

2026春节习俗大全
2026春节习俗大全

本专题整合了2026春节习俗大全,阅读专题下面的文章了解更多详细内容。

189

2026.02.11

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
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号