当前位置: 首页 > news >正文

C++17中std::any的使用

      类sdk:any提供类型安全的容器来存储任何类型的单个值。通俗地说,std::any是一个容器,可以在其中存储任何值(或用户数据),而无需担心类型安全。void*的功能有限,仅存储指针类型,被视为不安全模式。std::any可以被视为void*的类型安全替代品。
      std::any初始化:拷贝初始化;使用参数化构造函数;大括号初始值设定(brace initializer);使用赋值运算符;使用std::make_any。
      必须使用std::any_cast<type>(any_var)函数将any_var值转换为原始类型。std::any_cast<type>(any_var)函数有一些重载,它可以返回副本、引用或指针,具体取决于调用方式。如果存储值的类型不是尝试转换的类型,则编译器将抛出std::bad_any_cast异常或返回nullptr转换期间的类型必须与原始类型完全相同

int test_any_init()
{// copy initialisationstd::any value = 66; // 推荐: std::any value = std::make_any<int>(66); // std::make_any:类型安全、异常安全std::cout << "value: " << std::any_cast<int>(value) << "\n"; // value: 66// assignment operatorvalue = "China";std::cout << "value: " << std::any_cast<const char*>(value) << "\n"; // value: China// parametrized constructorstd::any value2(88.);std::cout << "value2: " << std::any_cast<double>(value2) << "\n"; // value2: 88// brace initializertry {std::any value3{ "China" };std::cout << "value3: " << std::any_cast<std::string>(value3) << "\n"; // std::any_cast<const char*>(value3)} catch (std::bad_any_cast& e) {std::cout << "Error: " << e.what() << "\n"; // value3: Error: Bad any_cast}auto value4 = std::make_any<std::string>("Beijing");std::cout << "value4: " << std::any_cast<std::string&>(value4) << "\n"; // value4: Beijing 推荐转换为引用类型来避免创建临时对象std::string str = "Tianjin";std::any value5 = std::move(str);std::cout << "value5: " << std::any_cast<std::string&>(value5) << "\n"; // value5: Tianjinreturn 0;
}

      std::any的成员函数
      (1).emplace:改变存储的对象,直接构造新对象;
      (2).reset:通过调用对象的析构函数来销毁存储的对象;
      (3).has_value:用于检查对象是否存储值;
      (4).type:返回一个type_info结构体,可用于获取存储对象的属性,如存储值的类型ID

int test_any_member_functions()
{// emplace, typestd::any value = 6;std::cout << "value: " << std::any_cast<int>(value) << "\n"; // value: 6std::cout << "type name: " << value.type().name() << "\n"; // type name: int(windows), i(linux)auto& tmp = std::any_cast<int&>(value); // 引用tmp = 8;std::cout << "value: " << std::any_cast<int>(value) << "\n"; // value: 8std::any_cast<int&>(value) = 10;std::cout << "value: " << std::any_cast<int>(value) << "\n"; // value: 10auto ptr = std::any_cast<int>(&value); // 指针std::cout << "value: " << *ptr << "\n"; // value: 10// 避免抛异常auto ptr2 = std::any_cast<std::string>(&value);if (ptr2 == nullptr)std::cout << "value dons't contain a string\n"; // value dons't contain a stringvalue.emplace<std::string>("China");std::cout << "value: " << std::any_cast<std::string>(value) << "\n"; // value: Chinastd::cout << "type name: " << value.type().name() << "\n"; // windows: type name: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >// linux:   type name: NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEif (value.type() == typeid(std::string))std::cout << "value type is std::string\n"; // value type is std::string// reset, has_valueif (value.has_value()) std::cout << "value found\n"; // value foundvalue.reset();if (!value.has_value()) std::cout << "no value found\n"; // no value foundstd::any tmp2;if (!tmp2.has_value()) std::cout << "tmp2 no value found\n"; // tmp2 no value found// std::any的主要问题是额外的动态内存分配std::cout << "size(any): " << sizeof(std::any) << "\n"; // size(any): 64(windows 10 vs2022), 16(ubuntu22.04 g++ 11.4)value = std::vector<int>{ 1, 2, 3 };std::cout << "value size: " << std::any_cast<std::vector<int>&>(value).size() << "\n"; // value size: 3return 0;
}

      执行结果如下图所示:注意:windows与linux上的差异

      尽管std::any为C++提供了很大的灵活性,但std::any的主要问题是额外的动态内存分配(堆内存)。由于容器不知道所包含的对象,因此动态分配成为任何对象都必须的。
      如果你了解所存储的类型(除了所存储的类型必须是可复制的这一事实之外),那么std::any可能不是合适的工具:它的灵活性会带来性能成本。如果恰好存在一个这样的类型T,则应该使用std::Optional。如果要存储的类型始终是具有特定签名的函数对象(例如回调),那么你需要std::function。如果你只需要存储编译时固定的某个集合中的类型,std::variant是一个不错的选择

      GitHub:https://github.com/fengbingchun/Messy_Test

相关文章:

  • 【教3妹学编程-算法题】2914. 使二进制字符串变美丽的最少修改次数
  • 如何从站长的角度选择高防CDN以节省成本
  • Python基础入门例程36-NP36 谁的数字大(运算符)
  • 部署ELK
  • [Machine Learning][Part 8]神经网络的学习训练过程
  • Windows下pm2调用npm和nuxt的办法
  • 【LeetCode刷题-栈与队列】--232.用栈实现队列
  • 论文阅读:One Embedder, Any Task: Instruction-Finetuned Text Embeddings
  • git reflog 恢复git reset --hard 回退的内容
  • 小程序如何设置用户同意服务协议并上传头像和昵称
  • Spring Boot spring.factories的原理
  • dockerfile避坑笔记(VMWare下使用Ubuntu在Ubuntu20.04基础镜像下docker打包多个go项目)
  • 算法——多数相和
  • 网络工程师进阶课:华为HCIP认证课程介绍
  • Python|Pyppeteer获取威科先行文章链接(21)
  • ES6指北【2】—— 箭头函数
  • Android组件 - 收藏集 - 掘金
  • angular2 简述
  • C++11: atomic 头文件
  • electron原来这么简单----打包你的react、VUE桌面应用程序
  • jquery ajax学习笔记
  • js操作时间(持续更新)
  • Node项目之评分系统(二)- 数据库设计
  • uva 10370 Above Average
  • 持续集成与持续部署宝典Part 2:创建持续集成流水线
  • 二维平面内的碰撞检测【一】
  • 干货 | 以太坊Mist负责人教你建立无服务器应用
  • 基于webpack 的 vue 多页架构
  • 前端_面试
  • 前端技术周刊 2019-02-11 Serverless
  • 前端每日实战 2018 年 7 月份项目汇总(共 29 个项目)
  • 如何使用 OAuth 2.0 将 LinkedIn 集成入 iOS 应用
  • 入手阿里云新服务器的部署NODE
  • 使用 @font-face
  • 用mpvue开发微信小程序
  • 职业生涯 一个六年开发经验的女程序员的心声。
  • const的用法,特别是用在函数前面与后面的区别
  • 数据库巡检项
  • 昨天1024程序员节,我故意写了个死循环~
  • ​3ds Max插件CG MAGIC图形板块为您提升线条效率!
  • ${ }的特别功能
  • $Django python中使用redis, django中使用(封装了),redis开启事务(管道)
  • (Matalb回归预测)PSO-BP粒子群算法优化BP神经网络的多维回归预测
  • (Repost) Getting Genode with TrustZone on the i.MX
  • (解决办法)ASP.NET导出Excel,打开时提示“您尝试打开文件'XXX.xls'的格式与文件扩展名指定文件不一致
  • (三)centos7案例实战—vmware虚拟机硬盘挂载与卸载
  • (一)Mocha源码阅读: 项目结构及命令行启动
  • (中等) HDU 4370 0 or 1,建模+Dijkstra。
  • (转)自己动手搭建Nginx+memcache+xdebug+php运行环境绿色版 For windows版
  • .equal()和==的区别 怎样判断字符串为空问题: Illegal invoke-super to void nio.file.AccessDeniedException
  • .Net - 类的介绍
  • .NET Core 和 .NET Framework 中的 MEF2
  • .NET Core 通过 Ef Core 操作 Mysql
  • .NET Core工程编译事件$(TargetDir)变量为空引发的思考
  • .NET Reactor简单使用教程