引自<http://www.cppblog.com/qinqing1984/archive/2011/07/10/150584.aspx>
我们知道一个空的类,也就是其内部没有非静态数据成员,没有虚指针(包括指向虚函数表和虚基类子对象的指针),它的大小通常为1,当然在某些对齐要求严格系统上可能是另一个数(通常是4),如果空类被继承,那么派生类的大小会怎么样呢?一个支持C++标准和EBO的编译器对此会进行空基类的优化,也就是不给空的基类子对象分配空间,换句话说,空基类子对象的地址和其派生类实例的地址是相同的。从编译器实现的角度来看,需要考虑继承时的不同情况,下图中P表示父类,C表示子类,圆形表示空类,矩形表示非空类。单继承EBO情况如下图所示


优化应用
由于空基类优化技术节省了对象不必要的空间,提高了运行效率,因此成为某些强大技术的基石,基于类型定义类如stl中的binary_function、unary_function、iterator、iterator_traits的实现复用;基于策略类如内存管理、多线程安全同步的实现复用。当某个类存在空类类型的数据成员时,也可考虑借助EBO优化对象布局,例如下
1
template
<
typename T1,typename T2
>
2
class
EBO
3
{
4
private:
5
T1 m_t1;
6
T2 m_t2;
7
}
;

2

3

4

5

6

7

1
template
<
typename T1,typename T2
>
2
class
EBO : T1, T2
3
{
4
}
;

2

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
}
;

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

1
template
<
typename T1,typename T2
>
2
class
EBO: boost::compressed_pair
<
T1,T2
>
3
{
4
}
;

2

3

4
