std::any是c++17引入的类型安全容器,用于运行时存储任意可复制类型的单个值,通过类型擦除实现泛型暂存;核心操作包括构造/赋值、显式类型转换取值(std::any_cast)、类型检查(type()或指针形式cast);支持int/String/double等可复制类型,不支持void/引用/数组/抽象类等;适用于配置解析、插件传参等场景,性能敏感处推荐std::variant。

std::any 是 C++17 引入的类型安全容器,用于在运行时存储任意可复制(CopyConstructible)类型的单个值。它不是万能的“动态类型”,而是提供了一种类型擦除(type erasure)机制,在保证类型安全的前提下实现泛型数据暂存。
核心用法:构造、赋值与取值
std::any 的使用围绕三个关键操作展开:
- 构造/赋值:可直接用任意类型初始化,或通过
assign()替换内部值 - 取值:必须显式指定目标类型,调用
std::any_cast;类型不匹配会抛出(a) std::bad_any_cast - 类型检查:用
a.type() == typeid(T)或std::any_cast(返回指针,失败为 nullptr)做安全判断(&a)
示例:
#include #include #include std::any a = 42; // int a = std::string("hello"); // string,自动替换 a = 3.14; // double if (a.type() == typeid(double)) { double d = std::any_cast(a); // 安全取值 std::cout << d << "n"; } // 危险操作(抛异常): // int x = std::any_cast(a); // a 当前是 double,运行时报错
安全取值的两种推荐方式
避免程序崩溃,应优先使用以下任一方式检查后再取值:
立即学习“C++免费学习笔记(深入)”;
推荐指针方式(无异常开销,更轻量):
if (auto p = std::any_cast(&a)) { std::cout << "got string: " << *p << "n"; } else if (auto p = std::any_cast(&a)) { std::cout << "Got int: " << *p << "n"; }
常见限制与注意事项
std::any 并非“万能盒子”,需注意这些边界:
- 不支持 void、引用、数组、抽象类、不可复制类型(如 std::ostream)
- 默认构造的 std::any 为空(has_value() 返回 false),取值前务必检查
- 移动语义友好:移动后原对象变为空,避免意外访问
- 无隐式转换:不能像 python 那样直接打印或运算,所有操作都需显式 cast
典型应用场景
std::any 适合需要“临时携带类型不确定数据”的场景,例如:
- 配置项解析器:把不同字段(int/string/bool)统一存进 map
- 插件系统参数传递:宿主向插件函数传参时绕过模板约束
- 序列化中间表示:反序列化时暂存未确定类型的字段值
- 调试工具中的通用日志载荷
它不适用于高频访问或性能敏感路径——每次 cast 都有少量运行时开销和类型检查成本。若类型集合固定且有限,std::variant 通常是更高效、更安全的选择。