C++如何使用std::any存储任意类型数据

来源:苹果APP网作者:唐僧头衔:草根站长
导读:本期聚焦于小伙伴创作的《C++如何使用std::any存储任意类型数据》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《C++如何使用std::any存储任意类型数据》有用,将其分享出去将是对创作者最好的鼓励。

std::any是C++17标准库中提供的类型擦除容器,能够存储任意满足可拷贝构造条件的类型数据,并且在使用时可以通过类型检查确保取值安全,避免了传统void*指针带来的类型风险。

C++如何使用std::any存储任意类型数据

std::any的基本特性

std::any的核心能力是类型擦除,它会自动管理存储数据的生命周期,当std::any对象销毁时,内部存储的数据也会被自动释放。它支持存储基础类型、自定义类型、标准库容器等各类可拷贝构造的类型,但是不支持存储数组类型,也不支持存储引用类型。

存储数据到std::any

向std::any中存入数据非常简单,可以直接通过赋值操作或者构造函数完成,以下是基础示例:

#include <any>
#include <iostream>
#include <string>

int main() {
    // 存储int类型
    std::any a1 = 10;
    // 存储double类型
    std::any a2 = 3.14;
    // 存储字符串类型
    std::any a3 = std::string("hello std::any");
    // 存储自定义类型
    struct Person {
        std::string name;
        int age;
    };
    std::any a4 = Person{"张三", 20};
    return 0;
}

判断std::any中存储的类型

在从std::any中取出数据之前,需要先判断内部存储的类型是否符合预期,避免类型不匹配导致的异常。可以使用type()方法获取存储类型的type_info,再和目标类型对比:

#include <any>
#include <iostream>
#include <string>
#include <typeinfo>

int main() {
    std::any a = 100;
    // 判断存储的是否为int类型
    if (a.type() == typeid(int)) {
        std::cout << "存储的类型是int" << std::endl;
    }
    // 判断存储的是否为string类型
    if (a.type() == typeid(std::string)) {
        std::cout << "存储的类型是string" << std::endl;
    }
    return 0;
}

另外也可以使用has_value()方法判断std::any对象是否存储了有效数据:

#include <any>
#include <iostream>

int main() {
    std::any a;
    // 初始状态没有存储数据
    if (!a.has_value()) {
        std::cout << "当前std::any对象没有存储数据" << std::endl;
    }
    a = 50;
    if (a.has_value()) {
        std::cout << "当前std::any对象已经存储了数据" << std::endl;
    }
    return 0;
}

从std::any中取出数据

取出std::any中的数据有两种常用方式,分别是std::any_caststd::any_cast配合指针使用,两种方式在类型不匹配时的行为不同。

使用std::any_cast直接取值

如果类型匹配,会返回对应的值,如果类型不匹配,会抛出std::bad_any_cast异常:

#include <any>
#include <iostream>
#include <string>

int main() {
    std::any a = 200;
    try {
        // 正确取出int类型
        int val = std::any_cast<int>(a);
        std::cout << "取出的值: " << val << std::endl;
        // 错误尝试取出string类型,会抛异常
        std::string s = std::any_cast<std::string>(a);
    } catch (const std::bad_any_cast& e) {
        std::cout << "类型转换失败: " << e.what() << std::endl;
    }
    return 0;
}

使用std::any_cast取指针

这种方式不会抛出异常,如果类型匹配返回对应类型的指针,不匹配则返回空指针:

#include <any>
#include <iostream>
#include <string>

int main() {
    std::any a = std::string("test");
    // 取string类型指针
    std::string* sp = std::any_cast<std::string>(&a);
    if (sp != nullptr) {
        std::cout << "取出字符串: " << *sp << std::endl;
    }
    // 取int类型指针,返回空
    int* ip = std::any_cast<int>(&a);
    if (ip == nullptr) {
        std::cout << "类型不匹配,返回空指针" << std::endl;
    }
    return 0;
}

清空std::any中的数据

如果需要清空std::any中存储的数据,可以调用reset()方法,或者给它赋一个空的std::any对象:

#include <any>
#include <iostream>

int main() {
    std::any a = 100;
    std::cout << "清空前是否有值: " << a.has_value() << std::endl;
    // 方式1:调用reset
    a.reset();
    std::cout << "reset后是否有值: " << a.has_value() << std::endl;
    // 方式2:赋空值
    a = 200;
    a = std::any();
    std::cout << "赋空后是否有值: " << a.has_value() << std::endl;
    return 0;
}

使用注意事项

  • std::any只能存储可拷贝构造的类型,如果存储的类型没有拷贝构造函数,会导致编译错误。
  • 频繁使用std::any会带来一定的性能开销,因为类型擦除需要额外的内存和管理逻辑,对性能要求极高的场景需要谨慎使用。
  • 取出的数据如果是大型对象,建议使用引用或者指针的方式,避免不必要的拷贝。

典型应用场景

std::any适合用在需要存储多种不确定类型的场景,比如通用配置项存储,配置项可能是int、string、bool等不同类型,用std::any可以统一存储;还有消息总线的消息载荷存储,不同的消息可能携带不同类型的业务数据,用std::any可以灵活承载。

std::anyC++任意类型存储类型擦除修改时间:2026-07-17 19:36:30

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。