C++中存储不同类型数据主要依赖结构体、联合体、std::variant和std::any。结构体提供类型安全和清晰语义,但内存开销大且缺乏运行时灵活性;联合体节省内存但类型不安全,需手动管理判别器;std::variant在C++17中引入,是类型安全的联合体,支持编译时和运行时检查,兼顾内存效率与安全性;std::any通过类型擦除支持任意类型存储,灵活性高但有运行时开销和类型转换异常风险。选择时应根据类型集合是否已知、内存需求、类型安全要求及C++标准版本综合权衡,优先推荐struct/class处理固定结构,std::variant用于互斥类型,std::any用于动态未知类型,union仅在极致内存敏感且可控场景使用。

C++中存储不同类型数据,主要仰赖于其强大的组合类型机制,如结构体(
struct
class
union
std::variant
std::any
在C++中,组合类型是构建复杂数据结构的基础。当我们谈论存储不同类型数据时,这通常意味着我们需要一个单一的实体,能够根据上下文持有多种可能的数据形态。
最基础也最常用的方法是结构体(struct
class
Person
std::string name
int age
double height
当内存效率成为关键考量,并且我们确定在任何给定时刻,只需要存储这些不同类型中的一个时,联合体(union
union
int
double
int
立即学习“C++免费学习笔记(深入)”;
现代C++17引入的std::variant
union
std::visit
如果连存储的类型集合都无法预先确定,或者说我们需要一个能够持有任意类型(只要它是可复制构造的)的“万能”容器,那么std::any
std::any
std::any_cast
选择合适的组合类型,本质上是在编译时类型安全、运行时灵活性、内存效率和代码复杂度之间做权衡。
说实话,结构体(或类,因为在C++中它们的核心机制很相似,只是默认访问权限不同)是组合不同数据类型最直接、最常见的方式。它就像是把一堆相关的物品放进一个有明确标签的盒子。
优势:
Student
name
id
gpa
局限:
std::optional
Event
MeetingDetails
ConcertDetails
SportMatchDetails
Event
std::vector
std::variant
std::any
总的来说,结构体是构建稳定、可预测数据模型的首选,尤其适用于那些数据结构在设计时就明确且变化不大的场景。
联合体(
union
如何节省内存: 联合体的核心思想就是所有成员共享同一块内存空间。它的内存大小是其所有成员中最大成员的大小。举个例子,如果你有一个联合体,里面包含一个
int
double
int
int
double
double
int
潜在的陷阱:
int
double
enum
int
std::string
std::vector
一个典型的例子是,如果我们要解析一个网络包,其负载(payload)可能是文本、也可能是二进制数据。我们可以用一个联合体来存储这两种可能,但必须有一个额外的字段来指明当前负载的类型。如果忘记检查这个判别器就去访问数据,那后果就不好说了。在我看来,除非你真的对内存有极致的要求,并且能确保万无一失地管理好类型,否则
std::variant
std::variant
std::any
进入现代C++(C++17及以后),我们有了
std::variant
std::any
union
struct
家政服务平台系统包含家用电器安装清洗、搬家、家电维修、管道疏通、月嫂保姆、育儿陪护、上门开锁等多种服务项目,用户可以直接通过家政小程序咨询,在线预约服务类型,同时还设置有知识科普,给用户科普一些清洁保养小技巧,让用户能够足不出户就可以直接预约服务,方便又快捷。本项目使用微信小程序平台进行开发。使用腾讯专门的小程序云开发技术,云资源包含云函数,数据库,带宽,存储空间,定时器等,资源配额价格低廉,无需
0
std::variant
std::variant
union
优势:
std::variant
std::get<T>(my_variant)
std::get<index>(my_variant)
std::bad_variant_access
std::visit
std::variant
std::visit
variant
std::variant
std::string
std::vector
variant
variant
示例:
#include <variant>
#include <string>
#include <iostream>
std::variant<int, double, std::string> data;
data = 10; // 存储int
std::cout << std::get<int>(data) << std::endl; // 安全访问
// std::cout << std::get<double>(data) << std::endl; // 运行时抛出std::bad_variant_access
data = "Hello Variant"s; // 存储std::string
std::cout << std::get<std::string>(data) << std::endl;
// 使用std::visit
auto print_value = [](auto&& arg) {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, int>) {
std::cout << "Integer: " << arg << std::endl;
} else if constexpr (std::is_same_v<T, double>) {
std::cout << "Double: " << arg << std::endl;
} else if constexpr (std::is_same_v<T, std::string>) {
std::cout << "String: " << arg << std::endl;
}
};
std::visit(print_value, data);std::any
std::any
优势:
std::any
std::any
std::any_cast
局限:
std::any
std::variant
std::any
std::any_cast<T>(my_any)
std::bad_any_cast
std::any
示例:
#include <any>
#include <string>
#include <iostream>
std::any value;
value = 42; // 存储int
std::cout << std::any_cast<int>(value) << std::endl;
value = std::string("Hello Any"); // 存储std::string
std::cout << std::any_cast<std::string>(value) << std::endl;
try {
// 尝试以错误的类型访问,会抛出异常
std::cout << std::any_cast<double>(value) << std::endl;
} catch (const std::bad_any_cast& e) {
std::cerr << "Error: " << e.what() << std::endl;
}总结:
std::variant
std::any
std::variant
选择合适的组合类型来存储不同类型数据,这其实是一个设计决策,需要权衡多方面的因素,没有一劳永逸的答案。在我看来,这更像是一个决策树,你需要根据你的具体需求和场景来一步步判断。
数据类型集合是固定且已知的吗?
struct
class
std::variant
std::visit
union
enum
union
数据类型集合是动态的,或者无法预先知道,需要存储任意类型吗?
bad_any_cast
std::any
其他考量:
std::variant
std::any
boost::variant
boost::any
union
std::variant
struct
struct
std::any
std::any
struct
std::variant
union
std::any
if (any.has_value())
try-catch
总而言之,我的经验是:
struct
class
std::variant
std::any
union
不要为了追求“酷炫”或“灵活”而盲目选择
std::any
struct
class
std::variant
以上就是C++如何使用C++组合类型存储不同类型数据的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号