std::any 是类型安全的运行时万能容器,用于存储未知类型值并强制类型检查;支持构造/赋值存值,必须用 std::any_cast 取值(引用、指针、值三种方式),不支持比较、序列化,适用于配置解析、插件传参等场景。

std::any 是什么,能用来干啥
它是个类型安全的“万能容器”,专门解决「运行时才知道存什么类型」的问题。不是 void* 那种裸指针,也不是 union 那种手动管理,而是编译器帮你管住类型——取值前必须明确告诉它你想要什么类型,否则抛 std::bad_any_cast。
典型场景:配置项解析(YAML/JSON 里字段类型不固定)、插件系统传参、泛型回调参数封装。
怎么存值、取值,关键步骤不能漏
存值很简单:std::any 构造或赋值即可,支持移动语义;但取值必须用 std::any_cast,且行为分三种:
- 传入目标类型的引用(
&):成功返回引用,失败抛异常 - 传入目标类型的指针(
*):成功返回非空指针,失败返回nullptr,最安全的用法 - 传入目标类型本身(无修饰):只对可拷贝类型有效,且会触发一次拷贝,慎用
示例:
立即学习“C++免费学习笔记(深入)”;
std::any a = 42;
int* p = std::any_cast<int>(&a); // ✅ 安全,p 指向原值
if (p) { /* 使用 *p */ }
<p>std::any b = std::string("hello");
auto s = std::any_cast<std::string>(b); // ⚠️ 触发拷贝,注意开销常见踩坑:类型擦除后,这些事它不管
std::any 只负责保存和类型检查,其他都得你自己兜底:
- 不支持直接比较:
a == b编译不过,得自己解包再比 - 不支持序列化:里面是
int还是std::vector<double></double>,它不告诉你,type()返回的是std::type_info,不能跨 DLL/so 稳定比较 - 小对象优化有上限:通常 32 字节内走栈存储,超了就堆分配,频繁存大对象(如长字符串、大数组)会影响性能
- 不能存引用或数组类型:
std::any any_ref = &x编译失败,std::any arr = int[10]{}也不行——它只接受完整对象类型
和 std::variant、void* 比,什么时候选它
选 std::any 当且仅当你**完全无法在编译期枚举所有可能类型**。比如插件接口约定传 std::any,而插件作者 runtime 才决定塞个 MyCustomConfig 进去。
如果类型集合已知且有限,优先用 std::variant<int double std::string></int>:更轻量、无堆分配、支持访问者模式、编译期检查更严。
绝对别用 void* 去模拟——没类型信息,reinterpret_cast 一错就是 undefined behavior,调试起来纯靠猜。
真正难处理的其实是“怎么知道该 cast 成什么”。这问题 std::any 不回答,得靠外部协议、type_id 字段或者动态 RTTI 辅助判断。










