原文地址:http://ideage.javaeye.com/blog/210614

联合(union)在C/C++里面见得并不多,但是在一些对内存要求特别严格的地方,联合又是频繁出现,那么究竟什么是联合、怎么去用、有什么需要注意的地方呢?就这些问题,我试着做一些简单的回答,里面肯定还有不当的地方,欢迎指出!

1、什么是联合? 
   “联合”是一种特殊的类,也是一种构造类型的数据结构。 在一个“联合”内可以定义多种不同的数据类型, 一个被说明为该“联合”类型的变量中,允许装入该“联合”所定义的任何一种数据,这些数据共享同一段内存,已达到节省空间的目的(还有一个节省空间的类型:位域)。 这是一个非常特殊的地方,也是联合的特征。另外,同struct一样,联合默认访问权限也是公有的,并且,也具有成员函数。

2、联合与结构的区别? 
   “联合”与“结构”有一些相似之处。但两者有本质上的不同。在结构中各成员有各自的内存空间, 一个结构变量的总长度是各成员长度之和(空结构除外,同时不考虑边界调整)。而在“联合”中,各成员共享一段内存空间, 一个联合变量的长度等于各成员中最长的长度。应该说明的是, 这里所谓的共享不是指把多个成员同时装入一个联合变量内, 而是指该联合变量可被赋予任一成员值,但每次只能赋一种值, 赋入新值则冲去旧值。

3、如何定义? 
   例如:

    union test 
    { 
      test() { } 
      int office; 
      char teacher[5]; 
    }; 

定义了一个名为test的联合类型,它含有两个成员,一个为整型,成员名为office;另一个为字符数组,数组名为teacher。联合定义之后,即可进行联合变量说明,被说明为test类型的变量,可以存放整型量office或存放字符数组teacher。

4、如何说明? 
   联合变量的说明有三种形式:先定义再说明、定义同时说明和直接说明。 
   以test类型为例,说明如下:


    1) union test 
       { 
         int office; 
         char teacher[5]; 
       }; 
       union test a,b;    /*说明a,b为test类型*/ 
    2) union test 
       { 
         int office; 
         char teacher[5]; 
       } a,b; 
    3) union 
       { 
         int office; 
         char teacher[5]; 
       } a,b; 

经说明后的a,b变量均为test类型。 
    a,b变量的长度应等于test的成员中最长的长度,即等于teacher数组的长度,共5个字节。a,b变量如赋予整型值时,只使用了4个字节,而赋予字符数组时,可用5个字节。

5、如何使用? 
   对联合变量的赋值,使用都只能是对变量的成员进行。 
   联合变量的成员表示为:联合变量名.成员名 
   例如,a被说明为test类型的变量之后,可使用a.class、a.office 
   不允许只用联合变量名作赋值或其它操作,也不允许对联合变量作初始化赋值,赋值只能在程序中进行。 
   还要再强调说明的是,一个联合变量,每次只能赋予一个成员值。换句话说,一个联合变量的值就是联合变员的某一个成员值。

6、匿名联合 
   匿名联合仅仅通知编译器它的成员变量共同享一个地址,而变量本身是直接引用的,不使用通常的点号运算符语法.例如:


     #include <iostream> 
     void main() 
     { 
         union{ 
                int test; 
                char c; 
               };          
        test=5; 
        c=''a''; 
        std::cout<<i<<" "<<c; 
     } 

正如所见到的,联合成分象声明的普通局部变量那样被引用,事实上对于程序而言,这也正是使用这些变量的方式.另外,尽管被定义在一个联合声明中,他们与同一个程序快那的任何其他局部变量具有相同的作用域级别.这意味这匿名联合内的成员的名称不能与同一个作用域内的其他一直标志符冲突. 
    对匿名联合还存在如下限制: 
    因为匿名联合不使用点运算符,所以包含在匿名联合内的元素必须是数据,不允许有成员函数,也不能包含私有或受保护的成员。还有,全局匿名联合必须是静态(static)的,否则就必须放在匿名名字空间中。

7、几点需要讨论的地方: 
   1、联合里面那些东西不能存放? 
      我们知道,联合里面的东西共享内存,所以静态、引用都不能用,因为他们不可能共享内存。 
   2、类可以放入联合吗? 
      我们先看一个例子:


      class Test 
      { 
      public: 
          Test():data(0) { } 
      private: 
          int data; 
      };       typedef union _test 
     { 
              Test test; 
     }UI;

编译通不过,为什么呢? 
     因为联合里不允许存放带有构造函数、析够函数、复制拷贝操作符等的类,因为他们共享内存,编译器无法保证这些对象不被破坏,也无法保证离开时调用析够函数。

8、又是匿名惹的祸?? 
       我们先看下一段代码:


 1 class test 
 2 { 
 3         public: 
 4              test(const char* p); 
 5              test(int in); 
 6              const operator char*() const {return data.ch;} 
 7              operator long() const {return data.l;} 
 8         private: 
 9         enum type {Int, String }; 
10          union 
11          { 
12               const char* ch; 
13               int i; 
14          } datatype; 
15         type stype; 
16         test(test&); 
17         test& operator=(const test&); 
18 }; 
19    test::test(const char *p):stype(String),datatype.ch(p)     { } 
20    test::test(int in):stype(Int),datatype.l(i)     { } 
21 

看出什么问题了吗?呵呵,编译通不过。为什么呢?难道datatype.ch(p)和datatype.l(i)有问题吗? 
     哈哈,问题在哪呢?让我们来看看构造test对象时发生了什么,当创建test对象时,自然要调用其相应的构造函数,在构造函数中当然要调用其成员的构造函数,所以其要去调用datatype成员的构造函数,但是他没有构造函数可调用,所以出错。 
     注意了,这里可并不是匿名联合!因为它后面紧跟了个data!

9、如何有效的防止访问出错? 
       使用联合可以节省内存空间,但是也有一定的风险:通过一个不适当的数据成员获取当前对象的值!例如上面的ch、i交错访问。 
       为了防止这样的错误,我们必须定义一个额外的对象,来跟踪当前被存储在联合中的值得类型,我们称这个额外的对象为:union的判别式。 
       一个比较好的经验是,在处理作为类成员的union对象时,为所有union数据类型提供一组访问函数。

C++联合的更多相关文章

  1. Dynamics CRM 之ADFS 使用 WID 的独立联合服务器

    ADFS 的使用 WID 的独立联合服务器适用于自己的测试环境,常用的就是在虚机中使用. 拓扑图如下: wID:联合身份验证服务配置为使用 Windows 内部数据库

  2. Dynamics CRM 之ADFS 使用 WID 的联合服务器场

    使用 WID 的联合服务器场 默认拓扑 Active Directory 联合身份验证服务 (AD FS) 是联合服务器场,使用 Windows 内部数据库 (WID). 在这种拓扑, AD FS 使 ...

  3. Hibernate(5)—— 联合主键 、一对一关联关系映射(xml和注解) 和 领域驱动设计

    俗话说,自己写的代码,6个月后也是别人的代码……复习!复习!复习!涉及的知识点总结如下: One to One 映射关系 一对一单向外键(XML/Annotation) 一对一双向外键关联(XML/A ...

  4. Federated Identity Pattern 联合身份模式

    Delegate authentication to an external identity provider. This pattern can simplify development, min ...

  5. [占位-未完成]scikit-learn一般实例之十一:异构数据源的特征联合

    [占位-未完成]scikit-learn一般实例之十一:异构数据源的特征联合 Datasets can often contain components of that require differe ...

  6. SQL联合查询:子表任一记录与主表联合查询

    今天有网友群里提了这样一个关于SQL联合查询的需求: 一.有热心网友的方案: 二.我的方案: select * from ( select a.*,(select top 1 Id from B as ...

  7. Dynamics CRM 之ADFS 使用 SQL Server 的联合服务器场

    此拓扑用于 Active Directory 联合身份验证服务 (AD FS) 不同于使用 Windows 内部数据库 (WID) 部署拓扑,因为不会将数据复制到每台联合服务器场中的联合身份验证服务器 ...

  8. Dynamics CRM 之ADFS 使用 WID 和代理的联合服务器场

    为此部署拓扑 Active Directory 联合身份验证服务 (AD FS) 等同于联合服务器场与 Windows 内部数据库 (WID) 拓扑中,但它将代理服务器计算机添加到外围网络,以支持外部 ...

  9. Mysql联合,连接查询

    一. 联合查询    UNION, INTERSECT, EXCEPT UNION运算符可以将两个或两个以上Select语句的查询结果集合合并成一个结果集合显示,即执行联合查询.UNION的语法格式为 ...

  10. 利用联合双边滤波或引导滤波进行升采样(Upsampling)技术提高一些耗时算法的速度。

    这十年来,在图像处理领域提出了很多新的图像分析和处理方法,包括是自动的以及一些需要有人工参与的,典型的比如stereo depth computations.image colorization.to ...

随机推荐

  1. WebStorm设置编辑器中的字体大小

    启动webStorm之后,点击“FIle"菜单,选择其下的”Settings" 2.在左侧的菜单中选择“Editor/Colors & Fonts/Font 在右侧Sche ...

  2. 21个免费的UI设计工具和资源网站,不管是web,js,android都

    本帖最后由 hua631150873 于 2014-9-12 18:26 编辑 Lumzy 官方地址:http://www.lumzy.com/ Lumzy是一个网站应用和原型界面制作工具.使用Lum ...

  3. AChartEngine 安卓折线图 柱形图等利器

    http://www.eoeandroid.com/thread-548233-1-6.html 最近公司项目中要用到折线图,状态类型的图标要用到折线图,柱形图等,并且能够动态显示,在网上找了许多de ...

  4. iOS开发——UI基础-UIImage,UIImageView的使用

    1.UIImage 创建UIImage的两种方法 UIImage *image = [UIImage imageNamed:imageNmae]; UIImage *image = [UIImage ...

  5. 带你走进rsync的世界

    导读 Rsync(remote synchronize)是一个远程数据同步工具,可通过LAN/WAN快速同步多台主机间的文件,也可以使用 Rsync 同步本地硬盘中的不同目录.rsync共有3种使用方 ...

  6. Spatial pyramid pooling (SPP)-net (空间金字塔池化)笔记(转)

    在学习r-cnn系列时,一直看到SPP-net的身影,许多有疑问的地方在这篇论文里找到了答案. 论文:Spatial Pyramid Pooling in Deep Convolutional Net ...

  7. 数据流图DFD画法

    数据流图(DFD- Data Flow Diagram)让系统分析者弄清楚"做什么"的问题,其重要性就不言而喻了.那么我们怎么画数据流图呢?数据流图与系统流程图又有什么区别呢? 步 ...

  8. 应用HTK搭建语音拨号系统4: 识别器评估

    选自:http://maotong.blog.hexun.com/6261890_d.html 苏统华 哈尔滨工业大学人工智能研究室 2006年10月30日 声明:版权所有,转载请注明作者和来源 该系 ...

  9. EOS/普元:概述:中国IT业的悲哀

    公司引入了普元的EOS作为公司的基础架构平台,今后的所有项目将逐步向EOS的迁移,但对EOS的研究又让我不得不说出以下话: 1.EOS确实够简单,但未免简单过了头:从语言层面看EOS 因为EOS将成为 ...

  10. SQL Server被锁的表以及解锁

    select   request_session_id   spid,OBJECT_NAME(resource_associated_entity_id) tableName   from   sys ...