原文地址: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. CSS Image Sprite--网页图片应用处理方式

    CSS Sprites简介 CSSSprites在国内很多人叫css精 灵,是一种网页图片应用处理方式.它允许你将一个页面涉及到的所有零星图片都包含到一张大图中去,这样一来,当访问该页面时,载入的图片 ...

  2. oracle 行列转换的运用

    问题: 员工表: A(E_ID,NAME,) 部门表:  B(D_ID,D_NAME) 员工与部门关系:C(ID,E_ID,D_ID) SELECT  A.E_ID,A.NAME ,B.D_NAME ...

  3. vncserver和Ubuntu Xfce4远程桌面环境的配置,解决不显示图形界面

    vncserver和Ubuntu Xfce4远程桌面环境的配置 参考的http://blog.163.com/thinki_cao/blog/static/8394487520130301453180 ...

  4. Android开发App工程结构搭建

    本文算是一篇漫谈,谈一谈关于android开发中工程初始化的时候如何在初期我们就能搭建一个好的架构.      关于android架构,因为手机的限制,目前我觉得也确实没什么大谈特谈的,但是从开发的角 ...

  5. ios工程中加入.c/.cpp文件

    如果你在工程里拉入.c/.cpp文件就会导致工程报错, 现在有两种解决方式 1. 把.c文件的后缀全部改成.m的后缀 把.cpp文件的后缀改成.mm的后缀 2. 使用 工程名-Prefix.pch 并 ...

  6. Nmap扫描手册

    By:WHILE扫描类-sTTCP connect()扫描,完整的通话连接,容易被检测,会被记录日志.-sSTCP同步扫描,不完整的通话连接,很少有系统会记入日志.-sUUDP扫描-sAACK扫描用来 ...

  7. 11 AlarmHandler定时处理类——Live555源码阅读(一)基本组件类

    这是Live555源码阅读的第一部分,包括了时间类,延时队列类,处理程序描述类,哈希表类这四个大类. 本文由乌合之众 lym瞎编,欢迎转载 http://www.cnblogs.com/oloroso ...

  8. Java Log4j日志使用

    在程序中使用log4j 1.导入包import org.apache.log4j.Logger;import org.apache.log4j.PropertyConfigurator; 2.获取lo ...

  9. 7.2---蚂蚁相遇问题(CC150)

    public class Ants { public double antsCollision(int n) { // write code here return (1 - Math.pow(0.5 ...

  10. mysql 表关联查询报错 ERROR 1267 (HY000)

    解决翻案:http://stackoverflow.com/questions/1008287/illegal-mix-of-collations-mysql-error 即: SET collati ...