一、什么是C++ union?
在C++中,union
是一种可以存储不同类型数据的数据结构。union
与struct
很相似,只不过union
中所有成员共享同一块内存空间,用于节约内存空间。在访问union
的成员时,只会访问到最后一次赋值的成员,因此需要特别注意。
二、C++ union的定义与使用
在C++中,我们可以通过关键字union
定义一个union
类型。如下示例所示:
union MyUnion {
int i;
double d;
char c;
};
在这个例子中,我们定义了一个MyUnion
类型,包含了三个成员i
、d
、c
,i
和d
都占用8个字节,而c
只占用1个字节。
在使用union
时,可以通过.
或->
来访问union
的成员。但是需要注意的是,只会访问到最后一次赋值的成员:
MyUnion u;
u.i = 10;
cout << u.i << "\n"; // 输出10
u.d = 3.14;
cout << u.d << "\n"; // 输出3.14
cout << u.i << "\n"; // 输出不可预料结果
三、C++ union的内存分配与字节对齐
C++ union
的内存分配与字节对齐与C++ struct
类似。不同的是,union
中所有成员共享同一块内存空间,这意味着union
会将最大的成员的大小作为整个union
的大小,避免内存空间浪费。
在C中,进行内存分配时,通常都是按照机器的字节大小进行分配。因此C union
的成员变量通常也需要进行字节对齐。字节对齐的目的主要有两个:一是提高数据读取的效率;二是为了充分利用空间,避免内存空间的浪费。
举个例子,如果机器的字节大小为4个字节(32位),那么以下的MyUnion
类型的大小为8个字节,而不是5个字节:
union MyUnion {
char c;
int i;
};
这是因为机器需要按照4个字节的倍数来进行内存分配和字节对齐,而char
只占用1个字节,因此需要占用3个字节来进行分配和对齐,int
占用4个字节。
四、C++ union的应用场景
C++ union
的主要应用场景是节约内存空间,并且所有成员都是可以进行运算的基本类型。以下是C++ union
的两个应用场景:
1、联合体作为共用体使用
union
作为共用体使用时,可以用于将多个不同类型的变量共同拥有一块内存,实现对象之间的数据共享,从而节省内存。当共用体中的所有成员都包含了所有信息时,就可以使用共用体来实现在不同类型之间的相互转换,例如将int
转换为float
。
union MyUnion {
int i;
float f;
};
在上面的示例中,MyUnion
包含了i
和f
两个成员,它们共享同一块内存空间。可以通过以下方式来对MyUnion
进行访问:
MyUnion u;
u.i = 10;
cout << u.f << "\n"; // 输出不可预料结果
u.f = 3.14;
cout << u.i << "\n"; // 输出不可预料结果
在上面的示例中,不管以哪种方式进行访问,只会访问到最后一次赋值的成员。
2、联合体作为枚举类型使用
与枚举类型类似,联合体也可以用于枚举一组相关的值,例如:
union Color {
int i;
enum { RED, GREEN, BLUE } c;
};
在上面的示例中,我们定义了一个Color
类型,包含了i
和c
两个成员。其中,c
是一个枚举类型,包括了RED
、GREEN
和BLUE
三种取值,而i
则可以用于将c
转换为整型。
使用时可以通过以下方式进行访问:
Color c;
c.c = Color::RED;
cout << c.i << "\n"; // 输出0
c.c = Color::GREEN;
cout << c.i << "\n"; // 输出1
c.c = Color::BLUE;
cout << c.i << "\n"; // 输出2
五、C++ union的注意事项
使用C++ union
需要特别注意以下几点:
1、访问成员时需要注意
在访问union
的成员时,只会访问到最后一次赋值的成员,因此需要特别注意。
2、成员类型必须相同
在union
中所有成员的类型必须相同,否则会引起数据错误。
3、union不能包含有非静态成员函数
在union
中不能包含有非静态成员函数,这是因为所有成员都共享同一块内存空间,在访问函数时会出现问题。
六、总结
C++ union
是一种可以存储不同类型数据的数据结构,可以用于节约内存空间。在使用union
时需要特别注意其访问方式和成员类型。C++ union
的主要应用场景是节约内存空间,以及作为枚举类型使用。