参考文章 虚继承与空基类优化 。
class TEST_X {}; // 1
class TEST_Y : public virtual TEST_X { // 12
virtual void fun() {}; // 虚表4 //指虚基类的表指针4
char c; }; // 字节对齐 4 // 空基类优化为0
class TEST_Z : public TEST_X { // 8
virtual void fun() {}; // 空基类优化为 0
char c; }; // 字节对齐4 // 虚函数表4
class TEST_A : public TEST_Y, public TEST_Z {}; // 24
int main() {
cout << sizeof(TEST_X) << " " << sizeof(TEST_Y) << " "
<< sizeof(TEST_Z) << " " << sizeof(TEST_A) << endl;
return 0;
}
在vs的开发人员工具上使用 cl -d1reportSingleClassLayoutTEST_X 源.cpp
命令,查看各类的内存布局情况。
- C++标准规定,空类必须拥有非零的大小以保持对象的本质,使得这一class在实例化对象时得以在内存中配置独一无二的地址。
class TEST_X size(1):
+---
+---
- microsoft编译器引入所谓的virtual base class table。如果一个class有一个或多个virtual base classes,就会由编译器安插一个指针,指向virtual base class table。真正的virtual base class的指针就放在这个table中;
class TEST_Y size(12):
+---
0 | {vfptr}
4 | {vbptr}
8 | c
| <alignment member> (size=3)
+---
+--- (virtual base TEST_X)
+---
TEST_Y::$vftable@:
| &TEST_Y_meta
| 0
0 | &TEST_Y::fun
TEST_Y::$vbtable@:
0 | -4
1 | 8 (TEST_Yd(TEST_Y+4)TEST_X)
TEST_Y::fun this adjustor: 0
vbi: class offset o.vbptr o.vbte fVtorDisp
TEST_X 12 4 4 0
- 在TEST_Z中我们是普通的public继承,因此并没有产生{vbptr}指针。因此在该类中仅存在一个指向虚表的{vfptr}指针和内存对齐后占4字节的变量c
class TEST_Z size(8):
+---
0 | {vfptr}
4 | +--- (base class TEST_X)
| +---
4 | c
| <alignment member> (size=3)
+---
TEST_Z::$vftable@:
| &TEST_Z_meta
| 0
0 | &TEST_Z::fun
TEST_Z::fun this adjustor: 0
- 类TEST_A继承了两个类
class TEST_A size(24):
+---
0 | +--- (base class TEST_Y)
0 | | {vfptr}
4 | | {vbptr}
8 | | c
| | <alignment member> (size=3)
| +---
16 | +--- (base class TEST_Z)
16 | | {vfptr}
20 | | +--- (base class TEST_X)
| | +---
20 | | c
| | <alignment member> (size=3)
| +---
+---
+--- (virtual base TEST_X)
+---
TEST_A::$vftable@TEST_Y@:
| &TEST_A_meta
| 0
0 | &TEST_Y::fun
TEST_A::$vftable@TEST_Z@:
| -16
0 | &TEST_Z::fun
TEST_A::$vbtable@:
0 | -4
1 | 20 (TEST_Ad(TEST_Y+4)TEST_X)
vbi: class offset o.vbptr o.vbte fVtorDisp
TEST_X 24 4 4 0
有关空基类优化 http://www.cantrip.org/emptyopt.html
struct Bar { };
struct Foo {
struct Bar a[2];
struct Bar b;
};
Foo f;
-------------------------------------------------------
struct Baz
+-----------------------------------+
| +-------+-------+-------+-------+ |
| | Bar b | XXXXX | XXXXX | XXXXX | |
| +-------+-------+-------+-------+ |
| +-------------------------------+ |
| | int* p | |
| +-------------------------------+ |
+-----------------------------------+
空类类型的基础类子对象可能为零大小。(空基类优化,基类为空类时,优化为0字节)
struct Baz {
Bar b;
int* p;
};
-----------------------------------------------------
struct Baz2
+-----------------------------------+
| +-------------------------------+ |
| | int* p | |
| +-------------------------------+ |
+-----------------------------------+