空基类优化EBO之深度探索

空基类优化EBO之深度探索
继承情景
   我们知道一个空的类,也就是其内部没有非静态数据成员,没有虚指针(包括指向虚函数表和虚基类子对象的指针),它的大小通常为1,当然在某些对齐要求严格系统上可能是另一个数(通常是4),如果空类被继承,那么派生类的大小会怎么样呢?一个支持C++标准和EBO的编译器对此会进行空基类的优化,也就是不给空的基类子对象分配空间,换句话说,空基类子对象的地址和其派生类实例的地址是相同的。从编译器实现的角度来看,需要考虑继承时的不同情况,下图中P表示父类,C表示子类,圆形表示空类,矩形表示非空类。单继承EBO情况如下图所示
   EBO-1反映的是空类派生自空基类,EBO-2反映的是非空类派生自空基类,EBO-3、EBO-4反映的是在继承链中,对空基类的优化能不能传递到后代中。多继承EBO如下图所示
空基类优化EBO之深度探索_第1张图片
   EBO-5反映的是空类派生自两个空基类,EBO-6反映的是非空类派生自两个空基类,EBO-6反映的是空类派生自一个非空基类和一个空基类,EBO-7反映的是非空类派生自一个非空基类和一个空基类。以上8种情况,不论是单继承还是多继承,一个完全支持EBO的编译器就应该能把空基类部分都优化掉。

优化应用
    由于空基类优化技术节省了对象不必要的空间,提高了运行效率,因此成为某些强大技术的基石,基于类型定义类如stl中的binary_function、unary_function、iterator、iterator_traits的实现复用;基于策略类如内存管理、多线程安全同步的实现复用。当某个类存在空类类型的数据成员时,也可考虑借助EBO优化对象布局,例如下
1 template < typename T1,typename T2 >
2 class  EBO
3 {
4private:
5    T1 m_t1;
6    T2 m_t2;
7}
;
    当T1和T2为空类时,可以改进如下
1 template < typename T1,typename T2 >
2 class  EBO : T1, T2
3 {
4}
;
   
    更进一步,如果T1或T2为非类类型,如基本内建类型、函数指针等;或T1和T2类型相同时,则直接继承它们会导致编译错误,怎么办呢?这时可以添加一个中间层来解决,代码如下
 1 template < typename T1,typename T2, bool  isSame, bool  isFirstEmpty, bool  isSecondEmpty >
 2 class  EBO_IMPL;
 3
 4 template < typename T1,typename T2 >
 5 class  EBO_IMPL < T1,T2, false , false , false >
 6 {
 7    T1 m_t1;
 8    T2 m_t2;
 9}
;
10
11 template < typename T1,typename T2 >
12 class  EBO_IMPL < T1,T2, false , true , true >  : T1,T2
13 {
14}
;
15
16 template < typename T1,typename T2 >
17 class  EBO_IMPL < T1,T2, false , true , false >  : T1
18 {
19    T2 m_t2;
20}
;
21
22 template < typename T1,typename T2 >
23 class  EBO_IMPL < T1,T2, false , false , true >  : T2
24 {
25    T1 m_t1;
26}
;
27
28 template < typename T1,typename T2 >
29 class  EBO_IMPL < T1,T2, true , false , false >
30 {
31    T1 m_t1;
32    T2 m_t2;
33}
;
34
35 template < typename T1,typename T2 >
36 class  EBO_IMPL < T1,T2, true , true , true >  : T1
37 {
38    T2 m_t2;
39}
;
40
41 template < typename T1,typename T2 >
42 class  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后,代码如下
1 template < typename T1,typename T2 >
2 class  EBO: boost::compressed_pair < T1,T2 >
3 {
4}
;

你可能感兴趣的:(空基类优化EBO之深度探索)