共用体通过共享内存节省空间,所有成员共用同一内存区域,大小由最大成员决定,适用于变体类型、硬件映射等场景,但需手动管理当前激活成员,不能含非平凡构造的类,现代C++推荐使用std::variant替代。

在C++中,union(共用体)是一种特殊的数据类型,允许在相同的内存位置存储不同的数据类型。它通过内存共享机制实现节省内存的目的,适用于某些特定场景下的内存优化。下面详细说明其工作原理和使用限制。
内存共享机制:同一块内存被多个成员共用
共用体的所有成员共享同一段内存空间,其大小等于最大成员所需的字节数。这意味着任何时候只能有一个成员处于有效状态。
例如:
union Data {
int i;
float f;
char str[8];
};
这个 Data 共用体的大小为 8 字节(由 char str[8] 决定),无论你使用哪个成员,都使用这 8 字节中的同一区域。
- 当你给 i 赋值后,再读取 f,结果是未定义的(位模式解释不同)
- 共用体不会自动记录当前激活的是哪个成员,程序员必须自行管理
如何节省内存:避免为多个互斥字段分配独立空间
在资源受限或需要高效存储的场景下,共用体非常有用。典型应用包括:
立即学习“C++免费学习笔记(深入)”;
- 表示一种“变体”类型,比如某个变量在不同情况下可能是整数、浮点数或字符串指针
- 硬件寄存器映射:同一组寄存器在不同模式下代表不同含义
- 网络协议解析:某些字段根据标志位解释为不同类型
如果使用 struct 存储上述 Data 类型的三个字段,总大小至少是 int + float + char[8] 的对齐总和,通常远大于 8 字节。而 union 只需最大成员的空间,显著减少内存占用。
使用限制与注意事项
尽管能节省内存,但共用体有严格的使用约束:
- 不能包含具有非平凡构造函数、析构函数或拷贝控制的类类型(如 std::string、std::vector)
- C++11 起支持带构造函数的类,但需手动管理生命周期(使用 placement new 和显式析构)
- 访问非当前写入的成员属于未定义行为,编译器不作检查
- 无法继承其他类,也不能作为基类
- 不支持 static 成员变量
为安全使用共用体,常配合一个枚举标记当前状态:
struct SafeData {
enum Type { INT, FLOAT, STRING } type;
union {
int i;
float f;
char str[8];
};
void setInt(int val) {
type = INT;
i = val;
}
// 使用前检查 type 判断当前有效成员
};
基本上就这些。共用体适合对内存敏感且能严格控制状态切换的底层编程场景,但现代C++更推荐使用 std::variant(C++17)来替代,它提供了类型安全的多态存储,虽然略有运行时开销,但更安全易用。










