C++怎么使用any_C++任意类型容器教程【灵活】

3次阅读

std::any是单值类型擦除容器,仅支持存储一个可复制类型的值,不能自动管理多值或类型调度;它要求类型具拷贝构造、析构不抛异常,取值需显式类型检查,性能低于std::variant。

C++怎么使用any_C++任意类型容器教程【灵活】

std::any 不是“任意类型容器”,它是单值包装器,存一个值、取一个值;想存多个不同类型的值,得自己管理 vector<:any> 或类似结构,但别指望它自动帮你做类型调度或迭代安全。

std::any 能存什么、不能存什么

它能存任何可复制(Copyconstructible)类型的值,包括自定义类、intstd::String、甚至 std::vector<double></double> —— 但不能存不完整类型、抽象类对象、或者没有拷贝构造函数的类型(比如只含移动构造的类,除非你显式 move 赋值)。

常见错误现象:std::any a = std::move(my_unique_ptr); 编译失败,因为 std::unique_ptr 不可拷贝;得用 a = std::any{std::move(my_unique_ptr)}; 才行。

  • 必须确保被存类型的析构函数不抛异常(否则 std::any 析构可能中止)
  • std::any(默认构造)调用 value() 会抛 std::bad_any_cast,不是空指针或默认值
  • 类型擦除带来小开销:每次 value() 都要运行时比对 type_info,频繁调用注意性能

怎么安全地取出值:别跳过类型检查

直接 std::any_cast<t>(a)</t> 强制转型,失败就抛异常;更稳妥的是先用 a.type() == typeid(T) 判断,或用指针版 std::any_cast<t>(&a)</t> —— 返回 T*空指针表示类型不匹配。

立即学习C++免费学习笔记(深入)”;

使用场景:解析配置项时,键值对的 value 存为 std::any,读取前根据 schema 知道该转成 int 还是 bool,这时指针版更合适,避免异常开销。

  • 别写 auto x = std::any_cast<int>(a);</int> 就完事,没检查就 crash
  • std::any_cast 对 const 和引用有重载,std::any_cast<const int>(a)</const> 可避免拷贝
  • 如果不确定类型,又不想写一 if (a.type() == typeid(...)),说明设计可能该用 std::variant

和 std::variant 的关键区别在哪

std::any 是运行时完全擦除类型,std::variant 是编译期限定一组可能类型,空间更紧凑、访问更快、无异常风险(用 std::visit 安全分发)。

性能影响明显:100 万次取值,std::variant 通常比 std::any 快 2–5 倍,且无动态分配(除非装大对象)。

  • 如果你知道所有可能类型(比如 json 解析只可能是 int/double/std::string/nullptr_t),用 std::variant 更稳
  • std::any 适合插件系统、脚本绑定这类“真不知道将来塞啥”的场景
  • 两者都不支持直接序列化;想保存/传输,得自己加类型 tag 和序列化逻辑

最容易被忽略的是:std::any 没有 operator==,也没 hash 支持。想比较两个 any,得先确认类型相同,再手动 cast 后比值 —— 这部分逻辑没人替你写,漏掉就等于没做相等判断。

text=ZqhQzanResources