c++中如何使用std::any存储任意类型_c++17 any容器用法

12次阅读

std::any可安全存储任意可复制类型,但取值必须用std::any_cast显式转换,类型不匹配时抛std::bad_any_cast异常;建议先用has_value()检查或使用指针版any_cast避免异常。

c++中如何使用std::any存储任意类型_c++17 any容器用法

std::any 可以安全地存储任意可复制类型,但不能直接取值,必须用 std::any_cast 显式转换——类型不匹配会抛出 std::bad_any_cast 异常。

std::any 的基本存取操作

构造时支持任意可复制类型(包括自定义类),但注意:空的 std::any 不能直接 any_cast;取值前建议先用 has_value() 检查,或用指针版 any_cast(&a) 避免异常。

  • std::any a = 42; —— 自动推导并存储 int
  • std::any b = std::String("hello"); —— 存储 std::string
  • int x = std::any_cast(a); —— 成功,返回副本
  • const std::string* s = std::any_cast<:string>(&b); —— 返回指针,失败时为 nullptr,更安全

std::any_cast 类型不匹配时的行为

当目标类型与内部实际类型不一致(包括 cv 限定、引用、指针差异),std::any_cast(a) 会立即抛出 std::bad_any_cast。这不是编译错误,而是运行时异常,容易在未覆盖分支中触发崩溃。

  • std::any a = 3.14;,然后 std::any_cast(a) → 抛异常
  • std::any_cast(a) 是合法的(const 引用匹配)
  • std::any_cast(a) 无效:不能对内部值取地址,只能取 const 引用或值

性能与内存开销需要注意的地方

std::any 内部通常采用小对象优化(SOO):小类型(如 intbool、短 std::string)直接存于对象内;大类型则分配。这意味着频繁存取大对象会有额外分配/释放开销,且移动语义不一定被完全利用。

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

  • 默认构造或赋值 std::any{} 是空状态,has_value() 返回 false
  • 移动赋值(a = std::move(other))会转移资源,但原 other 变为空
  • 避免把 std::any 放在 tight loop 中反复构造/析构,尤其含 std::vectorstd::string
std::any get_config_value(const std::string& key) {     static std::map cfg = {         {"timeout", 30},         {"enabled", true},         {"host", std::string("localhost")}     };     auto it = cfg.find(key);     return (it != cfg.end()) ? it->second : std::any{}; } 

// 安全读取示例 if (auto p = std::any_cast(&get_config_value("timeout"))) { int timeout = *p; // 使用 } else { // 处理缺失或类型不符 }

真正麻烦的不是怎么存,而是每次取值都得面对类型不确定性——你得知道它“应该是什么”,或者准备好 fallback 和错误路径。别把它当万能容器滥用,更适合配置传递、插件接口、反射桥接这类明确上下文的场景。

text=ZqhQzanResources