新闻中心

C++怎么使用std::any和std::variant_C++17类型安全容器详解

2025-12-03
浏览次数:
返回列表
std::any可存储任意类型,适用于类型未知但需安全访问的场景;std::variant是类型安全的联合体,适用于预定义类型的集合,二者均避免了void*的类型不安全问题。

c++怎么使用std::any和std::variant_c++17类型安全容器详解

在C++17中,std::anystd::variant 是两个新增的类型安全容器,它们解决了传统 void* 或联合体(union)带来的类型不安全问题。虽然两者都能存储不同类型的数据,但适用场景和设计目标不同。下面详细介绍它们的使用方法与区别。

std::any:任意类型的容器

std::any 可以保存任意单一类型的值,类似于“万能盒子”。它适用于你无法提前知道要存储什么类型,但又需要类型安全的场景。

基本用法:

GoEnhance GoEnhance

全能AI视频制作平台:通过GoEnhance AI让视频创作变得比以往任何时候都更简单。

GoEnhance 347 查看详情 GoEnhance
  • 包含头文件:#include <any></any>
  • 创建 any 对象并赋值:

std::any a = 42;         // 存整数<br>a = std::string("hello"); // 改为字符串

访问值的方法:

  • 使用 std::any_cast 提取值,注意类型必须匹配,否则抛出 std::bad_any_cast 异常:

try {<br>   int value = std::any_cast<int>(a);<br>} catch (const std::bad_any_cast&) {<br>   // 类型错误处理<br>}

  • 也可以用指针形式避免异常:

if (auto p = std::any_cast<double>(&a)) {<br>   std::cout << *p;<br>} else {<br>   std::cout << "not double";<br>}

注意事项:

  • any 不支持直接比较操作(==, !=)
  • 性能开销较大,因为涉及动态内存分配和类型信息存储
  • 适合配置、参数传递等灵活性要求高的场景

std::variant:类型受限的多选一容器

std::variant 是一个“类型安全的联合体”,只能保存其模板参数中列出的某一种类型。相比 any 更高效且可控。

基本用法:

  • 包含头文件:#include <variant></variant>
  • 定义可存储的类型列表:

std::variant<int, std::string, double> v;<br>v = 42;           // ok<br>v = "hello"s;     // ok<br>// v = true;      // 编译错误,bool 不在允许列表中

访问 variant 中的值:

  • 使用 std::get<t>(v)</t>std::get<index>(v)</index>,类型或索引错误会抛出 std::bad_variant_access
  • 更推荐使用 std::visit 进行类型安全的访问:

std::visit([](const auto& val) {<br>   std::cout << val;<br>}, v);

visit 会根据当前存储的类型自动调用对应的 lambda 分支,是处理 variant 的最佳实践。

初始化与状态检查:

  • 默认构造时,variant 会初始化为其第一个类型的默认值(前提是该类型可默认构造)
  • 可用 std::holds_alternative<t>(v)</t> 检查当前是否存的是某种类型:

if (std::holds_alternative<std::string>(v)) {<br>   std::cout << "it's a string";<br>}

any 与 variant 如何选择?

关键在于使用场景:

  • 需要存储完全未知的类型,比如插件系统、反射机制、通用容器 —— 用 std::any
  • 已知可能的类型集合,比如表达式求值中的 int/double/string,JSON 基本类型 —— 用 std::variant

variant 性能更好,类型更明确,编译期可检查;any 更灵活但运行时开销大。

常见陷阱与建议

  • 不要对 any 频繁使用 any_cast,容易出错,建议配合 type info 判断
  • variant 中如果某个类型不可默认构造,需显式初始化
  • 使用 visit 时,lambda 要能处理所有可能类型,否则编译失败
  • 避免嵌套过深的 variant,会影响可读性和性能

基本上就这些。std::any 和 std::variant 让 C++ 在保持类型安全的前提下拥有了更强的泛型能力,合理使用可以替代不少不安全的 void* 或 union 用法。

以上就是C++怎么使用std::any和std::variant_C++17类型安全容器详解的详细内容,更多请关注其它相关文章!


# 第一个  # 静安抖音营销推广电话  # 网站seo关键词分类  # 商业内容关键词排名  # 合肥网站建设的微博  # 济南seo公司推荐  # seo49  # 福州排名seo公司  # 网站SEO优化案例分析  # 天门网站如何推广  # 手机病毒网站建设海报图  # c++  # 迭代  # 头文件  # 是一个  # 的是  # 命令行  # 抛出  # 解决方法  # 适用于  # 不安全  # 区别 


相关栏目: 【 科技资讯46185 】 【 网络学院92790


相关推荐: 抖音DOU+怎么投最有效 抖音付费推广的ROI提升技巧  J*a递归快速排序中静态变量导致数据累积的陷阱与解决方案  魅族17怎样用浏览器译外语网页_iPhone魅族17浏览器译外语网页【即时翻译】  如何在离线环境中使用Composer_Composer离线安装依赖包的技巧与策略  AO3中文官网链接_AO3网页版稳定镜像站  谷歌google账号注册详细步骤 谷歌账号注册官方教程  AO3官方镜像站点汇总 AO3同人作品网页版直达链接  《燕云十六声》两周内达九百万玩家!位居畅销榜第五  电脑屏幕颜色不舒服怎么办_Windows夜间模式与色彩校准教程【护眼技巧】  age动漫网站入口 age动漫官网直接访问入口  海量存储:机器视觉智能化的核心基石  Highcharts 雷达图径向轴标签定制指南:利用多Y轴实现数值标注  qq浏览器如何查看和导出已保存的密码 qq浏览器密码管理器数据备份教程  苹果手机指南针不准怎么校准 传感器校准方法详解【建议收藏】  微信网页版官方入口教程 微信网页版网页版快速登录步骤  如何将HTML表格多行数据保存到Google Sheet  Excel如何用迷你图显趋势_Excel用迷你图显趋势【趋势小图】  AO3网页版最新入口合集 Archive of Our Own在线访问指南  印象笔记怎样用批量导出备知识库_印象笔记用批量导出备知识库【备份方法】  Win10桌面图标出现小盾牌怎么办 Win10去除UAC图标教程【解决】  MAC如何将整个网页截长图_MAC使用Safari的导出为PDF或第三方工具  Win11怎么合并任务栏图标 Win11开启任务栏合并减少图标占空间【方法】  使用 Pandas 高效处理 .dat 文件:数据清洗与数值计算实战  PDO预处理语句中冒号的正确处理:区分SQL函数格式与命名占位符  12306选座怎么选到商务座_12306商务座选择与配置说明  Python字典中优雅地迭代剩余元素的方法  12306怎么选座位选到安静区_12306选座安静区域选择策略  使用 Pandas 高效处理 .dat 文件:字符清理与数据计算  响应式CSS Grid布局:优化网格项在小屏幕下的堆叠与宽度适配  黑鲨3Pro怎样在相册开漫画风滤镜_iPhone黑鲨3Pro相册开漫画风滤镜【趣味滤镜】  快手赚钱渠道_快手收益来源  PHP中获取MongoDB服务器运行时间(Uptime)的专业指南  解决Bootstrap卡片顶部边距导致背景图下移的问题  vivo浏览器自带的下载器速度慢怎么办 vivo浏览器提升文件下载速度的技巧  必由学在线入口 必由学网页版快速登录入口  在Go开发中优雅管理ListenAndServe进程:GoSublime集成方案  QQ邮箱电脑版登录入口_QQ邮箱官方网站登录平台  如何优雅地扩展SprykerGlue后端API授权逻辑,使用spryker/glue-backend-api-application-authorization-connector-extension  React/Next.js中实现列表项的动态移动与状态管理:兼论唯一键的重要性  蛙漫官网漫画入口地址_蛙漫在线畅读无广告弹窗  想当下一个《2077》?《心之眼》Steam评价升至"多半好评"  Gmail邮箱申请注册直达_Gmail邮箱免费注册PC版官网入口2025  网站内容防复制粘贴的实现策略与局限性  J*a里如何使用N*igableMap进行导航操作_可导航Map操作技巧解析  如何使用Rector自动化升级旧代码_通过Composer安装和配置Rector进行代码重构  Golang如何测试channel通信行为_Golang channel通信测试与分析方法  AO3官方可用镜像 Archive of Our Own网页版最新入口  CSS条件样式无法按设备触发怎么排查_media条件语句正确设置解决触发问题  深入理解Google Cloud Datastore查询:祖先路径与数据一致性  支付宝解绑银行卡步骤_支付宝如何解除绑定银行卡 

搜索