C++联合
目录 |
1 联合简介
联合是一个结构,但结构的数据成员各自占用一块内存空间, 它们形成一个整体, 所占空间是全部成员所占空间的总和。联合与此不同, 它的数据成员重叠挤占同一段内存空间, 有点像"一套班子, 多块招牌", 它们形成的整体, 所占空间取成员中占用空间最大者。
2 定义与声明
下面定义了一个名为test的联合类型,它含有两个成员,一个为整型,成员名为office;另一个为字符数组,数组名为teacher。联合定义之后,即可进行联合变量声明,被声明为test类型的变量,可以存放整型量office或存放字符数组teacher。
union test { test() { } int office; char teacher[5]; };
声明分为三种方式:
- 第一种,先定义再声明:
union test { test() { } int office; char teacher[5]; }; union test a,b; //说明a,b为test类型
- 第二种,定义时同时声明:
union test { test() { } int office; char teacher[5]; } a,b;
- 第三种,直接声明,之后再也不能再添加其他的变量:
union { test() { } int office; char teacher[5]; } a,b;
3 联合的使用
对联合变量的赋值,使用都只能是对变量的成员进行。
联合变量的成员表示为:联合变量名.成员名
例如,a被说明为test类型的变量之后,可使用a.class、a.office
不允许只用联合变量名作赋值或其它操作,也不允许对联合变量作初始化赋值,赋值只能在程序中进行。
还要再强调说明的是,一个联合变量,每次只能赋予一个成员值。换句话说,一个联合变量的值就是联合变员的某一个成员值。
4 匿名联合
匿名联合仅仅通知编译器它的成员变量共同享一个地址,而变量本身是直接引用的,不使用通常的点号运算符语法。例如:
#include <iostream> void main() { union{ int test; char c; }; test=5; c='a'; std::cout<<i<<" "<<c; }
正如所见到的,联合成分象声明的普通局部变量那样被引用,事实上对于程序而言,这也正是使用这些变量的方式。另外,尽管被定义在一个联合声明中,他们与同一个程序快那的任何其他局部变量具有相同的作用域级别。这意味这匿名联合内的成员的名称不能与同一个作用域内的其他一直标志符冲突。
对匿名联合还存在如下限制:
- 因为匿名联合不使用点运算符,所以包含在匿名联合内的元素必须是数据,不允许有成员函数,也不能包含私有或受保护的成员。
- 全局匿名联合必须是静态(static)的,否则就必须放在匿名名字空间中。
- 联合里面的东西共享内存,所以静态、引用都不能用,因为他们不可能共享内存。
- 不允许存放带有构造函数、析够函数、复制拷贝操作符等的类,因为他们共享内存,编译器无法保证这些对象不被破坏,也无法保证离开时调用析够函数。
5 如何有效的防止访问出错
使用联合可以节省内存空间,但是也有一定的风险:联合内的数据共享内存,而且同时只能有一个变量出现,因此就有可能出现交错访问的现象,即通过一个不适当的数据成员获取当前对象的值,比如
union Fudge{ int i; int *p; }; int* cheat(int i) { Fudge a; a.i = i; return a.p; //bad usee }
上例在使用的时候,内存中储存的是 i,但访问的却是 p,因此就会出现错误。为了防止这样的错误,我们必须定义一个额外的对象,来跟踪当前被存储在联合中的值得类型,我们称这个额外的对象为:union的判别式。
另一个比较好的经验是,在处理作为类成员的union对象时,为所有union数据类型提供一组访问函数。
6 参见
- C/C++中的联合 union. ︶ㄣ第二名. 2009-11-11.