《白话C++》第10章 Page31 10.2.5 Std::any

本文探讨了C++中如何通过std::any解决强类型语言下不同类型数据存储的问题,介绍了std::any的使用方法,以及其潜在的风险和限制,如类型转换异常处理。
摘要由CSDN通过智能技术生成

10.2.5 std::any

C++是一门强类型的语言,意味着一个“数据”的出现,必然要伴随着它有一个确定的类型。体现在STL中,各类容器都要求所存储的数据,它们的类型都必须是一致的

尽管是这些容器是模板,可以变幻出各种类型的容器,但每一个具体的容器对象,都只能存储一种类型的元素

解决办法一是在容器里存储指针,然后再new出不同的对象,这其中又有两种做法,一是C语言风格,存储一个“void * ”,再一个是面向对象的风格,设定一个共同的基类,然后存储该基类指针,实际new出的是各种派生类。

在C++ STL容器中直接存储指针,存在两个讨厌的地方,一是要记得最后需要清理这些指针delete);二是类型不安全。从容器中取出指针时,为了得到它的真实指向,往往需要强制转换。

问题具体化一下:现在有三个变量,把它们都存储在std::list <T>中:

std::string name = "D2"; //一个字符串
int age = 12;            //一个整数
std::vector <int> scores; //一个整数的vector

scores.push_back(91);
scores.push_back(92);

看起来要三个不同类型的list来分别存储:list <string>list <int>list <vector <int>>

std::any”可以解决这个问题。any是一个类,它被设计成可以持有各种类型的数据,对外则统统表现成一个类:any。这样一来,只需一个list <any>,就可以存储多种类型的数据了:

以any为元素类型的容器,简直像是吞食一样的鳄鱼。

036行的代码透露了一个“天机”,由于C++在类型转换“会帮一次忙”(当然它只帮一次忙)的功能,所以前面“用any包装”的工作其实时不必要的,可以用  list<any>:

lst.push_back(12)
lst.push_back(name)
lst.push_back(score)

从容器中取出时,数据还是any类型。

面对一个any类型的数据,要得到它原来的类型是什么,这只有靠强大的记忆力了。

跳过上述代码和list有关的操作,直接看一个数据变成any之后,再如何从any变回原身。

这个变回的过程,需要用到 any_cast <T>()操作,它和标准库的static_cast <>()、dynamic_cast<>()等等case操作有一致的界面。

boost :: any any1(std::string("D2")); //可以包装string
boost :: any any2(12); //可以包装整数
boost :: any any3(scores); //连容器都可以再包装

//现出“原形”
std::string s = boost::any_cast <std::string> (any1);
int i = boost::any_cast <int> (any2);
std::vector<int> v = boost::any_cast <std::vector <int>>(any3);

any的转换(转回原类型)发挥了C++强类型的优点,它会帮你检查类型兼容,如果转换出错,就抛出异常,如果不处理这个异常,程序就直接挂掉。

这个异常类型是“std::bad_any_cast”,下面尝试将一个std::list <int> 强制转换成一个int,这也太疯狂了。

【危险】:"any"的危险

一,是如果让any包装一个指针,则它并不会在其自身生命周期结束时,自动释放所持有的指针,这和STL的容器设计理念一致。

二,是从总体设计上讲,通常并不推荐积极使用any,应该只把any当成项目中某个小功能模块里解决某个小问题的一个小工具。

注意:使用std::any,需要支持C++17标准的编译器,否则可以考虑使用boost::any

  • 18
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值