空基类优化EBO之深度探索
一、EBO的背景
我们知道一个空的类,也就是其内部没有非静态数据成员,没有虚指针(包括指向虚函数表和虚基类子对象的指针),它的大小通常为1,当然在某些对齐要求严格系统上可能是另一个数(通常是4),如果空类被继承,那么派生类的大小会怎么样呢?一个支持C++标准和EBO的编译器对此会进行空基类的优化,也就是不给空的基类子对象分配空间,换句话说,空基类子对象的地址和其派生类实例的地址是相同的。从编译器实现的角度来看,需要考虑继承时的不同情况,下图中P表示父类,C表示子类,圆形表示空类,矩形表示非空类。单继承EBO情况如下图所示EBO-1反映的是空类派生自空基类,EBO-2反映的是非空类派生自空基类,EBO-3、EBO-4反映的是在继承链中,对空基类的优化能不能传递到后代中。多继承EBO如下图所示
EBO-5反映的是空类派生自两个空基类,EBO-6反映的是非空类派生自两个空基类,EBO-6反映的是空类派生自一个非空基类和一个空基类,EBO-7反映的是非空类派生自一个非空基类和一个空基类。以上8种情况,不论是单继承还是多继承,一个完全支持EBO的编译器就应该能把空基类部分都优化掉。二、EBO的应用
由于空基类优化技术节省了对象不必要的空间,提高了运行效率,因此成为某些强大技术的基石,基于类型定义类如stl中的binary_function、unary_function、iterator、iterator_traits的实现复用;基于策略类如内存管理、多线程安全同步的实现复用。当某个类存在空类类型的数据成员时,也可考虑借助EBO优化对象布局,代码描述如下
1template<typename T1,typename T2>
2class EBO
3{
4private:
5 T1 m_t1;
6 T2 m_t2;
7};
当T1和T2为空类时,可以改进如下1template<typename T1,typename T2>
2class EBO : T1, T2
3{
4};
进一步扩展考虑,如果T1或T2为非类类型,如基本内建类型、函数指针等;或T1和T2类型相同时,则直接继承它们会导致编译错误,怎么办呢?这时可以添加一个中间层来解决,代码如下
1template<typename T1,typename T2,bool isSame,bool isFirstEmpty,bool isSecondEmpty>
2class EBO_IMPL;
3
4template<typename T1,typename T2>
5class EBO_IMPL<T1,T2,false,false,false>
6{
7 T1 m_t1;
8 T2 m_t2;
9};
10
11template<typename T1,typename T2>
12class EBO_IMPL<T1,T2,false,true,true> : T1,T2
13{
14};
15
16template<typename T1,typename T2>
17class EBO_IMPL<T1,T2,false,true,false> : T1
18{
19 T2 m_t2;
20};
21
22template<typename T1,typename T2>
23class EBO_IMPL<T1,T2,false,false,true> : T2
24{
25 T1 m_t1;
26};
27
28template<typename T1,typename T2>
29class EBO_IMPL<T1,T2,true,false,false>
30{
31 T1 m_t1;
32 T2 m_t2;
33};
34
35template<typename T1,typename T2>
36class EBO_IMPL<T1,T2,true,true,true> : T1
37{
38 T2 m_t2;
39};
40
41template<typename T1,typename T2>
42class EBO : EBO_IMPL<T1,T2,boost::is_same<T1,T2>::value,boost::is_empty<T1>::value,boost::is_empty<T2>::value>
43{
44};
为了简便实现,上面代码直接使用了boost中的is_same,is_empty元函数来判断类型的属性,实际上boost中已经实现了EBO的选择运用工具即compressed_pair类模板,研究其源码可发现,该工具充分考虑到了T1和T2实际类型的各种情况,is_empty的判断是运用sizeof来比较类型大小确定的。替换compressed_pair后,代码如下
1template<typename T1,typename T2>
2class EBO: boost::compressed_pair<T1,T2>
3{
4};
补充:软件开发 , C语言 ,