0

0

c++中的std::variant和std::any的性能对比_c++类型安全容器选择【C++17】

冰火之心

冰火之心

发布时间:2025-12-24 13:37:02

|

543人浏览过

|

来源于php中文网

原创

c++kquote>std::variant 是编译期确定类型的零开销有限多态容器,栈上存储、无虚调用;std::any 是运行期类型擦除的无限多态容器,依赖堆分配、虚函数和类型检查,性能开销显著。

c++中的std::variant和std::any的性能对比_c++类型安全容器选择【c++17】

std::variant 和 std::any 都是 C++17 引入的类型安全容器,但设计目标和性能特征差异显著——variant 是编译期确定类型的“有限多态”,any 是运行期擦除类型的“无限多态”。性能上,variant 几乎无额外开销,any 则有动态内存、虚函数调用和类型信息查找等成本。

内存布局与访问开销

std::variant 在上直接存储其可选类型的**最大尺寸 + 1 字节(用于存放当前索引)**,访问时通过编译期生成的 switch 或跳转表完成,零运行时类型检查开销。例如:

std::variant v = 42;
// 访问 int:直接取地址偏移,无虚调用、无 new/delete

std::any 则内部持有一个指向堆内存的指针(除非小对象优化 SOO 生效),且每次访问需:

  • 调用 typeid 对比判断类型是否匹配
  • 若匹配,再解引用并 static_cast
  • 构造/析构过程涉及虚函数(如 std::any::holder 的 ~holder())

构造与赋值代价

variant 构造是 trivial 的(若所含类型都 trivial),即使非 trivial 类型,也只调用对应分支的构造函数,无额外抽象层。

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

any 的构造必然触发一次堆分配(除非 SOO 触发),且需保存类型信息(std::type_info*)和拷贝函数指针;赋值还可能引发新分配+旧释放。例如:

Magician
Magician

Figma插件,AI生成图标、图片和UX文案

下载
std::any a = std::string(1000, 'x'); // 很可能堆分配
a = 3.14; // 原 string 析构 + 新 double 存储(栈上,但需类型擦除逻辑)

适用场景决定性能取舍

选 variant 当你明确知道所有可能类型,且希望零成本抽象:

  • 解析器返回值(int/double/string/error)
  • 状态机状态(idle/running/paused)
  • AST 节点子类型集合固定

选 any 当你需要真正泛化的容器,比如插件系统参数、配置项、反射字段值:

  • 任意类型值的 map:std::map<:string std::any>
  • 回调函数参数打包
  • 无法在编译期枚举全部类型的场景

小对象优化(SOO)的影响

some std::any 实现(如 libstdc++ 和 MSVC)支持 SOO:对 sizeof ≤ 约 16–32 字节且无抛出析构的类型,直接存栈上,避免堆分配。但这不改变其运行时类型查询和虚函数调用的本质开销。

variant 没有 SOO 概念——它天生栈驻留,大小和访问路径完全静态可知。即使含 std::string,variant 仍只预留 max_size,不触发任何动态行为(除非你主动调用 string 的构造函数)。

基本上就这些。不是“哪个更快”,而是“哪个更合适”——variant 快得理所当然,any 慢得情有可原。用错场景,再快的 any 也救不了设计缺陷;用对地方,variant 的零成本就是最硬的性能保障。

相关专题

更多
string转int
string转int

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

311

2023.08.02

switch语句用法
switch语句用法

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

513

2023.09.21

Java switch的用法
Java switch的用法

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

401

2024.03.13

java多态详细介绍
java多态详细介绍

本专题整合了java多态相关内容,阅读专题下面的文章了解更多详细内容。

13

2025.11.27

java多态详细介绍
java多态详细介绍

本专题整合了java多态相关内容,阅读专题下面的文章了解更多详细内容。

13

2025.11.27

scripterror怎么解决
scripterror怎么解决

scripterror的解决办法有检查语法、文件路径、检查网络连接、浏览器兼容性、使用try-catch语句、使用开发者工具进行调试、更新浏览器和JavaScript库或寻求专业帮助等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

184

2023.10.18

500error怎么解决
500error怎么解决

500error的解决办法有检查服务器日志、检查代码、检查服务器配置、更新软件版本、重新启动服务、调试代码和寻求帮助等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

255

2023.10.25

string转int
string转int

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

311

2023.08.02

苹果官网入口直接访问
苹果官网入口直接访问

苹果官网直接访问入口是https://www.apple.com/cn/,该页面具备0.8秒首屏渲染、HTTP/3与Brotli加速、WebP+AVIF双格式图片、免登录浏览全参数等特性。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

10

2025.12.24

热门下载

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

精品课程

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

共18课时 | 3.9万人学习

Sass 教程
Sass 教程

共14课时 | 0.7万人学习

Pandas 教程
Pandas 教程

共15课时 | 0.8万人学习

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

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