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

news2024/11/24 1:38:03

      类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 initialisation
	std::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 operator
	value = "China";
	std::cout << "value: " << std::any_cast<const char*>(value) << "\n"; // value: China

	// parametrized constructor
	std::any value2(88.);
	std::cout << "value2: " << std::any_cast<double>(value2) << "\n"; // value2: 88

	// brace initializer
	try {
		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: Tianjin

	return 0;
}

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

int test_any_member_functions()
{
	// emplace, type
	std::any value = 6;
	std::cout << "value: " << std::any_cast<int>(value) << "\n"; // value: 6
	std::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: 8
	std::any_cast<int&>(value) = 10;
	std::cout << "value: " << std::any_cast<int>(value) << "\n"; // value: 10

	auto 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 string

	value.emplace<std::string>("China");
	std::cout << "value: " << std::any_cast<std::string>(value) << "\n"; // value: China
	std::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_traitsIcESaIcEEE

	if (value.type() == typeid(std::string))
		std::cout << "value type is std::string\n"; // value type is std::string

	// reset, has_value
	if (value.has_value()) std::cout << "value found\n"; // value found
	value.reset();
	if (!value.has_value()) std::cout << "no value found\n"; // no value found

	std::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: 3

	return 0;
}

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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1171467.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言实现输出一行文字中最长单词

完整代码&#xff1a; // 输出一行文字中最长单词 #include<stdio.h>#define N 20int main(){char str[N];printf("请输入一行文字\n");gets(str);//最长字符串的长度int max0;//str数组的下标int i0;//记录最长字符串在数组中的位置int flag0;//记录每个单词…

【sosp2023论文分享】Ditto:一个弹性自适应分离式内存缓存系统

Ditto: An Elastic and Adaptive Memory-Disaggregated Caching System 摘要 Ditto首先提出了一个以客户端为中心的缓存框架,以在DM的计算池中高效地执行各种缓存算法,只依赖于远程内存访问。然后,Ditto采用了一种分布式自适应缓存方案,该方案基于多个缓存算法的实时性能自…

链式二叉树的基本操作和相关OJ题训练(建议收藏!!!)

&#x1f493;博主csdn个人主页&#xff1a;小小unicorn ⏩专栏分类&#xff1a;数据结构&C &#x1f69a;代码仓库&#xff1a;小小unicorn的代码仓库&#x1f69a; &#x1f339;&#x1f339;&#x1f339;关注我带你学习编程知识 链式二叉树基本操作 二叉树节点设置二叉…

FMC驱动LCD

硬件简介 主控&#xff1a;STM32H750 LCD屏幕为16位并口屏幕 CubeMX配置 chip select: 选择起始地址块号&#xff0c;ADDR[27:26] Memory type: 内存类型&#xff0c;选择LCD Interface LCD Register Select: 根据选择计算映射地址, FSNC_A[25] Data: 数据宽度 NOR/PSRAM ti…

RISC-V与RISC Zero zkVM的关系

1. 引言 本文基本结构为&#xff1a; 编程语言背景介绍RISC-V虚拟机作为zkVM电路为何选择RISC-V&#xff1f; 2. 编程语言背景介绍 高级编程语言不专门针对某个架构&#xff0c;其便于人类编写。高级编程语言代码&#xff0c;经编译器编译后&#xff0c;会生成针对专门某架…

Azure 机器学习 - 设置 AutoML 训练时序预测模型

目录 一、环境准备二、训练和验证数据三、配置试验支持的模型配置设置特征化步骤自定义特征化 四、可选配置频率和目标数据聚合启用深度学习目标滚动窗口聚合短时序处理非稳定时序检测和处理 五、运行试验六、用最佳模型进行预测用滚动预测评估模型精度预测未来 七、大规模预测…

网络基础扫盲--TCP/UDP

博客内容&#xff1a;TCP/UDP 文章目录 一、TCP与UDP二、tcp可靠性如何保证&#xff1f;1、三次握手2、TCP报头3、TCP四次挥手 一、TCP与UDP tcp与udp都是传输层的协议&#xff0c;用于数据的传输。 对于tcp而言数据的传输会比较可靠&#xff0c;主要依赖于tcp面向链接的&…

openGauss学习笔记-114 openGauss 数据库管理-设置安全策略-设置帐号有效期

文章目录 openGauss学习笔记-114 openGauss 数据库管理-设置安全策略-设置帐号有效期114.1 注意事项114.2 操作步骤 openGauss学习笔记-114 openGauss 数据库管理-设置安全策略-设置帐号有效期 114.1 注意事项 创建新用户时&#xff0c;需要限制用户的操作期限&#xff08;有…

Prompt 设计与大语言模型微调,没有比这篇更详细的了吧!

本文主要介绍了Prompt设计、大语言模型SFT和LLM在手机天猫AI导购助理项目应用。 ChatGPT基本原理 “会说话的AI”&#xff0c;“智能体” 简单概括成以下几个步骤&#xff1a; 预处理文本&#xff1a;ChatGPT的输入文本需要进行预处理。 输入编码&#xff1a;ChatGPT将经过预…

如何使用Python和matplotlib绘制机器人运动偏差路径图——实用教程与代码解析

前言 科研论文中需要绘制一个精美的机器人运动路径图&#xff08;其中包含了机器人的期望运动路径和实际运动路径&#xff09;。我的期望路径是是一个方形&#xff0c;用Python代码是这样表示的&#xff1a; n_list [n1,n2,n3,n4] e_list [e1,e2,e3,e4] #n_list和e_list的各…

C++笔记之动态数组的申请和手动实现一个简单的vector

C笔记之动态数组的申请和手动实现一个简单的vector code review! 文章目录 C笔记之动态数组的申请和手动实现一个简单的vector1.C语言中动态数组的申请与使用1.动态数组的申请使用new和delete使用std::vector 1.std::vector的底层实现2.手动实现一个简单的vector:使用一个指向…

项目实战:展示第一页数据

1、在FruitDao接口中添加查询第一页数据和查询总记录条数 package com.csdn.fruit.dao; import com.csdn.fruit.pojo.Fruit; import java.util.List; //dao &#xff1a;Data Access Object 数据访问对象 //接口设计 public interface FruitDao {void addFruit(Fruit fruit);vo…

文件复制加密、文件落地加密、文件移动加密如何设置?

文件加密在保护信息安全方面具有重要作用。合格、好用的文件加密软件可以帮助企业保护商业机密、更遵守法律法规、提高企业核心竞争力、防止数据泄密等。 一般的加密都是对文件本身加密&#xff0c;比如加密某个WORD /PPT之类的&#xff0c;很少有能够加密某个文件夹的。今天就…

单链表基本操作的实现,初始化,头插,尾插,判空,获取个数,查找,删除,获取前置和后置位,清空,销毁

目录 一.单链表的设计 二.单链表的实现 三.单链表的总结 一.单链表的设计 1.单链表的结构定义: typedef struct Node{int data;//数据域struct Node* next;//后继指针}Node,*List; 2.单链表的设计示意图: 3.注意,单链表的最后一个节点的next域为NULL; 4.为什么要有一个头…

唯一ID如何生成,介绍一下目前技术领域最常使用的几种方法

纵使十面大山&#xff0c;又如何&#xff0c;无妨… 概述 唯一ID&#xff08;Unique Identifier&#xff09;是在计算机科学和信息技术领域中用于标识某个实体或数据的唯一标识符。生成唯一ID的方法可以根据具体需求和应用场景的不同而有所不同。以下是一些目前技术领域中常用…

2023-mac rz sz 安装

之前安装过一次&#xff0c;没问题&#xff0c;这次按照之前教程装了就不管上传下载都会卡住&#xff1b; step1: brew install lrzsz step2&#xff1a;在/usr/local/bin 路径下配置两个sh,之前从网上找到的直接用都不对&#xff0c;下面这个是调试过的正式可用的 iterm2…

【C语言进阶】之动态内存管理

【C语言进阶】之动态内存管理 1.为什么我们需要动态内存管理2.动态内存管理的函数介绍2.1malloc函数和free函数2.1.1malloc函数2.1.2 free函数 2.2calloc函数2.3realloc函数 3.动态内存管理中经常出现的一些问题总结。3.1 越界访问3.2 对空指针进行解引用操作3.3 对同一片空间进…

安全防御——二、ENSP防火墙实验学习

安全防御 一、防火墙接口以及模式配置1、untrust区域2、trust区域3、DMZ区域4、接口对演示 二、防火墙的策略1、定义与原理2、防火墙策略配置2.1 安全策略工作流程2.2 查询和创建会话 3、实验策略配置3.1 trust-to-untrust3.2 trust-to-dmz3.3 untrust-to-dmz 三、防火墙的区域…

归并排序--C语言实现

1. 简述 归并排序的原理是将&#xff0c;两个较大的数组分为大小几乎一致的两个数组。 再将两个数组进行合并成新的有序数组。 合并两个数组的时候需要额外的一个数组的空间。 2. 实现 上图说明过程 代码 #include <stdio.h>void Merge(int *arr, int *tmp, int …

freertos入门(stm32f10c8t6版闪烁灯)

首先到官网下载freertos源码&#xff0c;然后找一个stm32f10c8t6的空模板&#xff0c;这个空模板实现点灯之类的都行。 然后在这个空模板的工程下新建一个FreeRtos文件夹 接着在FreeRtos文件夹下新建三个文件夹&#xff0c;分别是src存放源码 inc 存放头文件&#xff0c;port …