Union (联合) 与C++ (转载与添加)

转载地址为: http://www.jellythink.com/archives/468

什么是union?

翻译过来说,就是共用体,或者也叫联合体。说到了union,也就是共用体,就不得不说一下struct了,当我们有如下的struct的定义时:

struct student
{
     char mark;
     long num;
     float score;
};

关于struct的内存结构,将就会像下图所示这样(在x86机器上演示):
sizeof(struct student)的值为12bytes。但是,当我们定义如下的union时,

union test
{
     char mark;
     long num;
     float score;
};

sizeof(union test)的值为4。这为什么呢?这就是需要说的。 有的时候,我们需要几种不同类型的变量存在在同一段的内存空间中,就像上面的,我们需要将一个char类型的mark、一个long类型的num变量和一个float类型的score变量存放在同一个地址开始的内存单元中。上面的三个变量,char类型和long类型所占的内存字节数是不一样的,但是在union中,它们都是从同一个地址存放的,也就是使用的覆盖技术,这三个变量互相覆盖,而这种使几个不同的变量共占同一段内存的结构,称为“共用体”类型的结构。上面定义的union类型的结构如下:

上面也说了,sizeof(union test)的值为4。那为什么是4呢?大体上来说,结构体struct所占用的内存为各个成员的占用的内存之和(当然也需要考虑内存对齐的问题了)。而对于union来说,在谭浩强的《C语言程序设计》中这么说:union变量所占用的内存长度等于最长的成员的内存长度。很显然,这是不对的,对于union所占用的内存大小,需要考虑内存对齐的问题。这就是为什么sizeof(union test)的值为4啦。

C中使用union

说的再好,再多,终归都是要在使用的,下面就好好的说说C中使用union。和struct一样,union只有先定义了共用体变量才能引用它。而且不能直接引用共用体变量,而只能引用共用体变量中的成员。就像我上面定义的union test。我们不能像下面这样直接引用union:

union test a;
printf("%d", a);

这种直接引用是错误的,由于a的存储区有好几种类型,分别占不同长度的存储区,仅写共用体变量名a,这样使编译器无法确定究竟输出的哪一个成员的值。所以,应该写成下面这样:

printf("%d", a.mark);

同时,在使用union的时候,我们还需要注意以下的几点:

  1. 同一个内存段可以用来存放几种不同类型的成员,但在每一个时刻只能存在其中一种,而不是同时存放几种。也就是说,每一瞬间只有一个成员起作用,其它的成员不起作用,即不是同时都存在和起作用。
  2. 共用体变量中起作用的成员是最后一个存放的成员,在存入一个新的成员后,原有的成员就失去作用。比如以下的代码:
    #include <iostream>
    using namespace std;
    
    union test
    {
         char mark;
         long num;
         float score;
    }a;
    
    int main()
    {
         // cout<<a<<endl; // wrong
         a.mark = ‘b‘;
         cout<<a.mark<<endl; // 输出‘b‘
         cout<<a.num<<endl; // 98 字符‘b‘的ACSII值
         cout<<a.score<<endl; // 输出错误值
    
         a.num = 10;
         cout<<a.mark<<endl; // 输出空
         cout<<a.num<<endl; // 输出10
         cout<<a.score<<endl; // 输出错误值
    
         a.score = 10.0;
         cout<<a.mark<<endl; // 输出空
         cout<<a.num<<endl; // 输出错误值
         cout<<a.score<<endl; // 输出10
     
         return 0;
    }

    所以,在使用union的时候,要十二分的小心的。

  3. 由于union中的所有成员起始地址都是一样的,所以&a.mark、&a.num和&a.score的值都是一样的。
  4. 不能把union变量作为函数参数,也不能使函数带回union变量,但可以使用指向union变量的指针。////现在已支持
  5. union类型可以出现在结构体类型定义中,也可以定义union数组,反之,结构体也可以出现在union类型定义中,数组也可以作为union的成员。

按理说,总结到这里,C语言中的union也就没什么更多的要说了。但是,有一种东西叫做C++,在这个C++中有一种东西叫做类。

当union遇到对象

就单单C中的union,上面的总结已经够用了,但是,现在偏偏又有一个叫做C++的东西;当union遇到了C++中的对象时,一切又变得剪不断,理还乱。上面总结的union使用法则,在C++中依然适用。本来union本就是从C语言中的,如果我们在C++中继续按照C语言的那种方式使用union,那是没有问题的。如果我们在union中放一个类的对象呢?结果会怎么样?比如有以下代码:

#include <iostream>
using namespace std;

class CA
{
     int m_a;
};

union Test
{
     CA a;
     double d;
};

int main()
{
     return 0;
}

可以看到,没有问题;如果我们在再类CA中添加了构造函数,或者添加析构函数,我们就会发现程序就会出现错误。由于union里面的东西共享内存,所以不能定义静态、引用类型的变量。由于在union里也不允许存放带有构造函数、析构函数和复制构造函数等的类的对象,但是可以存放对应的类对象指针。编译器无法保证类的构造函数和析构函数得到正确的调用,由此,就可能出现内存泄漏。所以,我们在C++中使用union时,尽量保持C语言中使用union的风格,尽量不要让union带有对象。

整理参考版如下:

// ConsoleApplication2.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <assert.h>

using namespace std;

class CA
{
    CA();
    int m_a;
};

class CB
{
    int m_b;
};

union Test
{
     char mark;
     long num;
     float score;
    // CA object; //error
     CB bobject; //correct;
     CA* pCA;
}a;

void teststring(char* const p)
{
    printf(p);

}

void MakeUnionAsPs(Test& as)
{
    printf("%d\r\n", as.num);

}

void MakeUnionAsPs1(Test* as)
{
    assert(as);
    printf("%d\r\n", as->num);

}

void MakeUnionAsPs2(Test as)
{
    printf("%d\r\n", as.num);

}

int _tmain(int argc, _TCHAR* argv[])
{
     // cout<<a<<endl; // wrong
     a.mark = ‘b‘;
     cout<<a.mark<<endl; // 输出‘b‘
     cout<<a.num<<endl; // 98 字符‘b‘的ACSII值
     cout<<a.score<<endl; // 输出错误值

     a.num = 10;
     cout<<a.mark<<endl; // 输出空
     cout<<a.num<<endl; // 输出10
     cout<<a.score<<endl; // 输出错误值

     a.score = 10.0;
     cout<<a.mark<<endl; // 输出空
     cout<<a.num<<endl; // 输出错误值
     cout<<a.score<<endl; // 输出10

     MakeUnionAsPs(a);
     MakeUnionAsPs1(&a);
     MakeUnionAsPs2(a);

     teststring("abcdg");

     return 0;
}
时间: 2024-10-22 13:12:12

Union (联合) 与C++ (转载与添加)的相关文章

union联合查询将两个表的查询结果在一个表中显示

表格ChannelReward和表格RewardSuppleSettle中都有一下几个字段JSMonth, ChannelNo, RewardSum, RewardItem.要将两个表中RewardSum>0的记录都显示在一个表中,可以使用联合查询 select * from(SELECT     JSMonth, ChannelNo, RewardSum, RewardItem, '1' AS ObjectTypeFROM         dbo.ChannelRewardWHERE    

[办公自动化] 再读《让EXCEL飞》(从excel导入access数据时,union联合查询,数据源中没有包含可见的表格)

一年多以前就买了@Mrexcel的<让excel飞>这本书.整体思路是利用access结合excel,大幅度提高数据分析效率. 最近又拿出来看了看.第十五章,比高级筛选更“高级”,P241.主要讲述多表关联查询,可以适用于一对多的场景. P248:联接属性的三种类型. Union联合查询可以用来实现同表头的多表数据合并. 但是将数据倒回到excel时,发现老是报错. 提示错误信息如下:数据源中没有包含可见的表格. 后来发现原因和解决方法如下: 借助Access中的可视化查询设计器,可以很大程度

SqlSever基础 union 联合查询,厉害的并集 重复项只显示一个 两个查询结果并在一起后排序

镇场诗:---大梦谁觉,水月中建博客.百千磨难,才知世事无常.---今持佛语,技术无量愿学.愿尽所学,铸一良心博客.------------------------------------------ 1 base code 1 use master 2 drop database helloworld 3 4 5 --创建一个数据库 6 create database helloworld 7 8 9 10 --用helloworld1这个数据库 11 use helloworld 12 13

12.Union联合

union Student { int age; char *name; } stu; union只按照最长的数据成员分配控件,适用于有N个数据不会同时出现的情况,用以压缩空间.

Mysql联合查询UNION和UNION ALL的使用介绍

UNION和UNION ALL的作用和语法 UNION 用于合并两个或多个 SELECT 语句的结果集,并消去表中任何重复行.UNION 内部的 SELECT 语句必须拥有相同数量的列,列也必须拥有相似的数据类型.同时,每条 SELECT 语句中的列的顺序必须相同.SQL UNION 语法: SELECT column_name FROM table1UNIONSELECT column_name FROM table2 注释:默认地,UNION 操作符选取不同的值.如果允许重复的值,请使用 U

【转】Mysql联合查询union和union all的使用介绍

Mysql的联合查询命令UNION和UNION ALL,总结了使用语法和注意事项,以及学习例子和项目例子,需要的朋友可以参考下 一.UNION和UNION ALL的作用和语法 UNION 用于合...... Mysql的联合查询命令UNION和UNION ALL,总结了使用语法和注意事项,以及学习例子和项目例子,需要的朋友可以参考下 一.UNION和UNION ALL的作用和语法 UNION 用于合并两个或多个 SELECT 语句的结果集,并消去表中任何重复行. UNION 内部的 SELECT

结构体struct 与 联合union

1.C语言中的结构体 1.1 定义 结构体是由一系列相同或不同类型的变量组成的集合. struct 结构体名{               //struct为关键字,“结构体名”为用户定义的类型标识. 数据类型1 成员名1;          //{ }中是组成该结构体的成员,其中数据类型可以是C语言所允许的任何数据类型. 数据类型2 成员名2; ... 数据类型n 成员名n; }; 1.2 结构体的内存分配(方法一) 结构体在内存中分配一块连续的内存,但结构体内的变量并不一定是连续存放的,这涉

C语言-枚举(enum)和联合(union)

使用enum进行定义 /* 枚举类型演示 */ #include <stdio.h> int main() { enum /*季节*/ {CHUN, XIA = 5, QIU, DONG}; printf("QIU是%d\n", QIU); } 使用union联合进行定义 /* 联合演示 */ #include <stdio.h> typedef union{ int val; float fval1; } tmp; int main(){ tmp utmp =

C++-结构体(struct),联合(union),枚举(enum)

使用struct定义结构体,使用Teacher t = {"", "", ""} 进行初始化操作 /* 结构体 */ #include <iostream> using namespace std; struct Teacher{ char name[20]; int age; double salary; void who(void) { cout << "名字是" << name <