019 C++的union类型
作者Lou Xiao, deepseek创建时间2025-04-02 15:08:35更新时间2025-04-02 15:08:35
1. Union 的基本概念
1.1 定义
- Union(联合体)是一种特殊的数据类型,允许在相同的内存位置存储不同的数据类型
- 语法:
union UnionName { member_list };
- 所有成员共享同一块内存空间
1.2 与结构体的区别
特性 | Union | Struct |
---|---|---|
内存使用 | 共享内存 | 每个成员有独立内存 |
大小 | 最大成员的大小 | 所有成员大小之和(考虑对齐) |
同时访问 | 只能访问一个活跃成员 | 可同时访问所有成员 |
2. Union 的基本用法
2.1 声明与定义
1.双击鼠标左键复制此行;2.单击复制所有代码。
1
union Data {
2
int i;
3
float f;
4
char str[20];
5
};
6
7
Data data; // 声明union变量
2.2 成员访问
1.双击鼠标左键复制此行;2.单击复制所有代码。
1
data.i = 10; // 使用int成员
2
cout << data.i;
3
4
data.f = 220.5; // 现在使用float成员
5
cout << data.f; // 此时data.i的值已被覆盖
2.3 大小计算
1.双击鼠标左键复制此行;2.单击复制所有代码。
1
cout << sizeof(Data); // 输出20,因为char str[20]是最大成员
3. Union 的高级特性
3.1 匿名Union (C++11)
1.双击鼠标左键复制此行;2.单击复制所有代码。
1
struct Widget {
2
enum class Type { INT, FLOAT, STRING } type;
3
4
union {
5
int i;
6
float f;
7
char s[20];
8
};
9
};
10
11
Widget w;
12
w.type = Widget::Type::INT;
13
w.i = 10; // 直接访问匿名union成员
3.2 带有构造函数的Union (C++11)
1.双击鼠标左键复制此行;2.单击复制所有代码。
1
union U {
2
string s; // 有非平凡构造函数的成员
3
int n;
4
5
U() : s("default") {} // 必须提供构造函数
6
~U() {} // 必须提供析构函数
7
};
3.3 受限Union (C++11)
- 当union包含有非平凡特殊成员函数的类型时:
- 默认构造函数被删除
- 必须自定义构造函数和析构函数
- 不能包含引用成员
4. Union 的应用场景
4.1 内存优化
- 当需要存储多种类型但不会同时使用时
- 在内存受限环境中节省空间
4.2 类型转换
1.双击鼠标左键复制此行;2.单击复制所有代码。
1
union Converter {
2
float f;
3
unsigned int u;
4
};
5
6
Converter c;
7
c.f = 3.14f;
8
cout << hex << c.u; // 输出浮点数的二进制表示
4.3 变体类型实现
- 结合enum实现简单的变体类型
1.双击鼠标左键复制此行;2.单击复制所有代码。
1
struct Variant {
2
enum { INT, FLOAT, STR } type;
3
union {
4
int i;
5
float f;
6
char s[20];
7
};
8
};
5. Union 的注意事项
5.1 活跃成员
- 任何时候只有一个成员是"活跃的"(存储了有效值)
- 访问非活跃成员是未定义行为(UB)
- 需要额外信息(如enum)来跟踪当前活跃成员
5.2 内存对齐
- Union的大小会按照最大成员的对齐要求进行对齐
1.双击鼠标左键复制此行;2.单击复制所有代码。
1
union AlignDemo {
2
char c; // 1字节
3
double d; // 8字节
4
}; // 大小可能是8而不是9
5.3 与C的兼容性
- C++中的union比C中的更严格
- C允许union包含结构体,C++进一步允许包含类(但有特殊要求)
6. C++17中的std::variant
6.1 Union的现代替代品
1.双击鼠标左键复制此行;2.单击复制所有代码。
1
#include <variant>
2
using var_t = std::variant<int, float, std::string>;
3
4
var_t v = 42; // 当前存储int
5
v = 3.14f; // 现在存储float
6
v = "hello"; // 现在存储string
6.2 与Union的比较
特性 | Union | std::variant |
---|---|---|
类型安全 | 不安全 | 安全 |
活跃成员跟踪 | 需要手动 | 自动 |
异常安全 | 无 | 有 |
可包含类型 | 有限制 | 几乎任何可复制类型 |
性能 | 更高 | 稍低 |
7. 最佳实践
- 优先考虑使用std::variant,除非有严格的性能需求
- 如果使用union,总是配合一个类型标签(enum)来跟踪活跃成员
- 避免在union中存储需要复杂构造/析构的类型
- 对union进行封装,提供类型安全的接口
- 注意跨平台问题,特别是涉及类型转换时
8. 示例代码
8.1 类型安全的Union封装
1.双击鼠标左键复制此行;2.单击复制所有代码。
1
class SafeUnion {
2
public:
3
enum Type { INT, FLOAT, STRING };
4
5
SafeUnion(int i) : type(INT) { data.i = i; }
6
SafeUnion(float f) : type(FLOAT) { data.f = f; }
7
SafeUnion(const char* s) : type(STRING) { strcpy(data.s, s); }
8
9
Type getType() const { return type; }
10
11
int getInt() const {
12
if (type != INT) throw std::runtime_error("Not an int");
13
return data.i;
14
}
15
// 类似getFloat(), getString()...
16
17
private:
18
Type type;
19
union {
20
int i;
21
float f;
22
char s[20];
23
} data;
24
};
8.2 Union在协议解析中的应用
1.双击鼠标左键复制此行;2.单击复制所有代码。
1
struct NetworkPacket {
2
uint8_t type;
3
union {
4
struct { uint32_t ip; uint16_t port; } connection;
5
struct { char filename[256]; } fileRequest;
6
struct { uint32_t chunks[8]; } dataChunk;
7
} payload;
8
};
文章目录