std::any是C++17引入的类型安全单值容器,可存储任意可复制构造类型(如int、std::string、自定义类、std::vector等),但不支持纯右值引用或不可复制类型。

std::any 是什么,能存哪些值
std::any 是 C++17 引入的类型安全容器,用来存储任意可复制(CopyConstructible)类型的单个值。它不是“万能容器”意义上的集合,而是一个“单值泛型盒子”——只能装一个东西,且必须明确知道怎么取出来。
- 可以存
int、std::string、自定义类(满足可复制)、甚至std::vector - 不能存纯右值引用、不满足复制构造的类型(如含 deleted 拷贝构造函数的类)
- 不支持直接比较两个
std::any是否相等(需手动type()判断后转型再比) - 存
nullptr是合法的,但存裸指针(如int*)本身没问题,只是要自己管理生命周期
常见误用:把它当 std::vector<:any> 用作动态类型数组——这可行但性能差、易出错,不是设计本意。
怎么安全地存和取值
存值很简单:std::any 构造或赋值即可;取值必须显式使用 std::any_cast,否则运行时报 std::bad_any_cast。
std::any a = 42;
std::any b = std::string("hello");
// ✅ 正确取值:类型匹配
int x = std::any_cast(a); // OK
std::string s = std::any_cast(b); // OK
// ❌ 错误:类型不匹配 → 抛 std::bad_any_cast
// double d = std::any_cast(a);
// ✅ 安全取值:先检查类型再 cast
if (a.type() == typeid(int)) {
int y = std::any_cast(a);
}
-
std::any_cast要求(any_obj) T和实际存储类型完全一致(包括 const/volatile 限定符) - 支持指针形式
std::any_cast,返回>(&any_obj) T,失败时返回nullptr,适合避免异常 - 不要用
std::any_cast—— 这是未定义行为(...)
和 void* / union / boost::any 对比有什么坑
-
和 void* 比:std::any 自动管理内存和析构,类型信息在运行时保留,但有约 2–3 倍空间开销(内部通常用 small buffer optimization + heap fallback)
立即学习“C++免费学习笔记(深入)”;
和 union 比:不需要手动维护活跃字段,但失去编译期类型检查和零成本抽象
和 boost::any 比:接口几乎一致,但 C++17 的 std::any 不支持移动捕获(move-only types),直到 C++23 才加入 std::any 的 move-only 支持(目前主流编译器仍按 C++17 实现)
常见性能陷阱:频繁构造/析构大对象(如 std::vector<:byte>(1MB))会触发堆分配,不如用 std::shared_ptr 包一层再存
编译依赖:必须开启 C++17 或更高标准(-std=c++17),GCC 7+、Clang 5+、MSVC 2017 15.0+ 支持
什么时候该用,什么时候不该用
和 void* 比:std::any 自动管理内存和析构,类型信息在运行时保留,但有约 2–3 倍空间开销(内部通常用 small buffer optimization + heap fallback)
立即学习“C++免费学习笔记(深入)”;
和 union 比:不需要手动维护活跃字段,但失去编译期类型检查和零成本抽象
和 boost::any 比:接口几乎一致,但 C++17 的 std::any 不支持移动捕获(move-only types),直到 C++23 才加入 std::any 的 move-only 支持(目前主流编译器仍按 C++17 实现)
常见性能陷阱:频繁构造/析构大对象(如 std::vector<:byte>(1MB))会触发堆分配,不如用 std::shared_ptr 包一层再存
编译依赖:必须开启 C++17 或更高标准(-std=c++17),GCC 7+、Clang 5+、MSVC 2017 15.0+ 支持
适用场景:
- 配置系统中需要混存不同类型的键值对(如 JSON-like 解析中间层)
- 插件接口中传递用户自定义参数,且无法提前约定类型
- 实现简易版类型擦除回调(配合
std::function)
不适用场景:
- 高频访问的热路径(每次
any_cast都有 type_info 比较开销) - 需要多态行为的场合(应该用虚函数或
std::variant) - 已知只有几种固定类型(优先选
std::variant,编译期检查 + 零分配)
std::any 的核心价值不在“万能”,而在“类型安全的运行时擦除”——它强迫你面对类型不确定性,并用显式转换承担责任。漏掉 type() 检查或乱 cast,崩得非常安静。











