计算机科学中,union指的是一个包含多种类型或者格式的值,或者数据结构包含这样的值。一些程序语言支持特殊的数据类型——union类型。换句话说,union类型的定义,规定了哪些类型存储在一起。比如,浮点或者长整型。相对于record类型,record类型定义为包含一个float和一个整型。而union则在一个时刻只能体现一种值。
此处提及的untion类型主要指untagged unions.与之相对的是tagged unions.
由于使用上的限制,untagged union类型通常只出现类型不安全的语言,或者以一种不安全的方法使用(C中)。对于tagged union类型来说,他们的优势在于不需要空间来存储tag。
Union和Structure的区别
从内存的角度来说,Union就是一个类,只不过,它所包含的所以的数据成员都在同一个地址上。因此Union对象的大小就是它所包含的数据类型中最大的那个。
而结构,所有的成员存储在连续的内存地址上,结构的大小就是所有成员类型大小的和。
在某些场合下,为了更有效的利用内存空间,程序逻辑必须确保读取的值是最新写的值。不然转型的时候可能会有异常抛出。下图是一个结构和union的内存分配示意图:
+-----+-----+
struct { int a; float b } gives | a | b |
+-----+-----+
^ ^
| |
memory location: 150 154
|
V
+-----+
union { int a; float b } gives | a |
| b |
+-----+
结构主要用在在当对象有多个对象组成,比如由2个整型组成,比如下面的x,y是并列的。
typedef struct {
int x; // x and y are separate
int y;
} tPoint;
Union则用于一个对象可以是任何类型,但是同一时间只能是一种类型,就和type-less存储系统那样。
typedef enum { STR, INT } tType;
typedef struct {
tType typ; // typ is separate.
union {
int ival; // ival and sval occupy same memory.
char *sval;
}
} tVal;
tagged union,也称作variant, variant record, discriminated union。tagged union和untagged union一样,也是一种数据类型,它可以接受多种不同的,但是固定的类型。同时间只有一种类型可以使用。tag 字段显式的表明哪一个在使用。可以认为是一个带有几个"case"的类型。当操作这种类型是,每一个case都要正确的处理。和普通的union类型一样,tagged union也是每个类型重叠使用存储区域。
tagged union在函数式语言中诸如ML和Haskell中是一种重要的类型,有时也称做变体,编译器能验证tagged union中的所有的case,避免类型错误。Tagged union通常和constructor这个概念一起出现。此处constructor不是指类的构造器。constructor生成 tagged union的值,初始化tag值。
tagged union对于untagged union的优势在于访问tagged union是安全的。Untagged union依靠程序逻辑来保证访问是安全的。tagged unions的缺点就是tag需要占据空间。