std::any只能存储可复制或可移动的完整对象,不支持void、数组、抽象类及拷贝构造被删除/私有的类型;它通过类型擦除实现但无运行时多态,不能替代std::shared_ptr。

std::any 能存什么,不能存什么
std::any 只能持有可复制(或可移动)的完整对象,不支持 void、数组类型(如 int[5])、抽象类、或带有删除/私有拷贝构造的类型。它内部用类型擦除实现,但不提供运行时多态行为——它不是 std::shared_ptr<interface></interface> 的替代品。
常见误用是试图存取引用:std::any 从不存储引用,std::any{&x} 实际存的是 x 的副本;想“假装”存引用,得用 std::reference_wrapper<t></t> 显式包装。
- ✅ 支持:
int、std::string、自定义struct(只要满足复制/移动要求) - ❌ 不支持:
void、int[]、std::function<void>&</void>、未定义拷贝构造的类 - ⚠️ 注意:
std::any拷贝开销取决于所存类型的大小和构造成本,频繁拷贝大对象(如std::vector<char></char>)会明显拖慢性能
如何安全地取出值:type_id 和 valueless_by_exception
取出前必须确认类型匹配,否则 std::any_cast 抛出 std::bad_any_cast。不能靠 try-catch 盲目尝试——应先用 type() 对比 typeid(T),或直接用带指针版本的 std::any_cast<t>(&any_obj)</t> 判断是否成功。
还要注意 std::any 可能处于 valueless by exception 状态(例如移动后源对象进入此状态),此时调用 type() 或 any_cast 都会抛异常。务必先用 any.has_value() 检查。
- 推荐写法:
if (auto p = std::any_cast<int>(&val)) { use(*p); }</int> - 避免写法:
int x = std::any_cast<int>(val);</int>—— 无检查,崩溃风险高 - 调试提示:打印类型可用
val.type().name(),但名字是编译器相关 mangled 名,建议配合typeid(int).name()对照看
实现一个 type-erased vector:std::vector<:any> 的封装要点
直接用 std::vector<:any></:any> 是最简方案,但裸用容易丢失类型信息和操作语义。加一层薄封装,能统一错误处理、支持按类型查找、避免重复 any_cast。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
关键设计点:不隐藏 std::any 的存在,而是暴露其约束;不重载 operator[] 返回 std::any&(易误用),改为提供 get<t>(size_t i)</t> 模板方法,并内置类型校验。
class any_vector {
std::vector<:any> data_;
public:
template<typename t> void push_back(T&& v) {
data_.emplace_back(std::forward<t>(v));
}
template<typename t> T* get(size_t i) {
if (i >= data_.size()) return nullptr;
return std::any_cast<t>(&data_[i]);
}
};</t></typename></t></typename></:any>
-
push_back用完美转发,避免多余拷贝 -
get<t></t>返回指针而非值,调用方可自行判断是否为空(即类型不匹配或越界) - 不提供
at()或operator[]的泛型版本——那会让用户绕过类型检查
为什么不用 std::any 做通用回调或事件总线
std::any 适合“临时暂存+明确知道类型”的场景,比如配置项解析、插件参数传递。但它不解决函数签名适配问题——你不能把 std::function<void></void> 存进 std::any 后,再以 std::function<void></void> 取出并调用。
真正需要运行时多态调度时,std::any 必须配合额外机制:比如用 std::type_index 做分发表,或结合 std::visit + std::variant(后者更适合有限类型集合)。拿 std::any 硬套事件系统,往往导致大量 dynamic_cast-风格的 any_cast 链,难以维护且无编译期保障。
一个容易被忽略的细节:std::any 的 type() 返回 std::type_info&,而 std::type_info::hash_code() 在跨 DLL/so 时可能不一致,若容器需在模块边界传递,建议改用字符串标识或枚举索引做类型标记。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










