union理解与妙用
来源:互联网 发布:透明计算造假 知乎 编辑:程序博客网 时间:2024/06/05 08:01
最近在看PCL中关于自定义PointT类型的文档,发现其中广泛使用了union,以前学习的时候用不到这个,也就没有留心,借此机会学习下union的使用方法,理解下union的本质。
一 struct和union内存结构
我们先来简单看下struct的内存结构,如下定义一个结构体:
struct student{ char mark; long num; float score;};
由于内存对齐的存在,这个student结构体的内存结构如下:
虽然mark理论上只有一个字节,但是却会占用4个字节的空间。
下面定义一个与student数据成员一样的union:
union union_student{ char mark; long num; float score;};
我们发现sizeof(union_student)的值为4,这就是union和struct的区别了。有时候,我们需要几种不同类型的变量存在在同一段的内存空间中,就像上面的,我们需要将一个char类型的mark、一个long类型的num变量和一个float类型的score变量存放在同一个地址开始的内存单元中。上面的三个变量,char类型和long类型所占的内存字节数是不一样的,但是在union中,它们都是从同一个地址存放的,也就是使用的覆盖技术,这三个变量互相覆盖,而这种使几个不同的变量共占同一段内存的结构,称为“共用体”类型的结构,也称“联合体”,也就是我们要说的union了,内存结构如下:
由上面,我们大致可以看出:结构体struct所占用的内存为各个成员的占用的内存之和(当然也需要考虑内存对齐的问题了)。而对于union来说,union变量所占用的内存长度等于最长的成员的内存长度,同样需要考虑内存对齐的问题。
二 union的使用
和struct一样,union只有先定义了共用体变量才能引用它。而且不能直接引用共用体变量,而只能引用共用体变量中的成员。
同时,在使用union的时候,还需要注意以下的几点:
1.同一个内存段可以用来存放几种不同类型的成员,但在每一个时刻只能存在其中一种,而不是同时存放几种。也就是说,每一瞬间只有一个成员起作用,其它的成员不起作用,即不是同时都存在和起作用。
2.共用体变量中起作用的成员是最后一个存放的成员,在存入一个新的成员后,原有的成员就失去作用。比如以下的代码:
union_student a;// cout<<a<<endl; // wronga.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; // 输出10cout << a.score << endl; // 输出错误值a.score = 10.0;cout << a.mark << endl; // 输出空cout << a.num << endl; // 输出错误值cout << a.score << endl; // 输出10
3.由于union中的所有成员起始地址都是一样的,所以&a.mark、&a.num和&a.score的值都是一样的。
4.union类型可以出现在结构体类型定义中,也可以定义union数组,反之,结构体也可以出现在union类型定义中,数组也可以作为union的成员。
三 union + 对象
当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带有对象。
四 理解PointT
我们先看一段代码:
#define PCL_ADD_UNION_NORMAL4D \ union EIGEN_ALIGN16 { \ float data_n[4]; \ float normal[3]; \ struct { \ float normal_x; \ float normal_y; \ float normal_z; \ }; \ };
这是PCL中定义normal(法向量)的源码。有了上面的知识,我们在来理解这个应该就没有问题了,其中:
- data_n[4] 为了内存对齐设计的
- normal[3] 和struct 里面的内容是主角,normal[3]方便我们进行整体的操作,而struct里面的内容则有助于我们访问normal中的各个分量,虽然直接normal[i]也可以,但是没有normal_x,normal_y,normal_z直观。这样的定义也有助于我们更好的理解代码。
- union理解与妙用
- union妙用
- 接口的妙用与理解
- union联合体的妙用
- Flink学习笔记 --- 理解ConnectedStream 与 Union
- 共用体union的妙用
- struct 和 union的妙用
- UNION与UNION ALL
- Union 与 Union ALl
- union 与 union all
- union 与union all
- union与union all
- union 与 union all
- union的0x3个妙用(II)
- union的0x3个妙用(I)
- 联合体union在立体几何中的妙用
- union在XMMATRIX里的妙用
- C语言中联合体union妙用
- Unity 脚本生命周期流程图
- 通过keydown,keyup,keypress事件监听输入框内内容的问题
- kali2.0安装搜狗输入法
- this 指针的地址--调用成员函数的所在对象的起始地址
- 面向对象的特征
- union理解与妙用
- Linux中的$()/``、$var/${var}、单引号(')、双引号(")
- Javascript模块化编程(二):AMD规范
- Android软键盘弹出或关闭监控
- 有序列表和无序列表 学习笔记
- CSS 中 # 和 . 的区别
- 子线程是否可以刷新UI视图?
- hibernate3.3.2学习笔记--- 一个小实例
- CRF++中文分词