C++对象模型——1.没有继承结构的类布局
2019-11-06 本文已影响0人
loki528
注: 64位VS下测试的结果,g++的实现可能不一样
#include <iostream>
using namespace std;
class A {
public:
int a;
virtual ~A() {
a = 0;
}
};
int main()
{
A* pa = new A();
cout << sizeof(A) << endl;
delete pa;
return 0;
}
输出
16
VS监视中pa的值
通过监视窗口可以看到pa指向的内存包含了两个成员:__vfptr和a。
__vfptr是个指针,指向一个数组。
A的对象模型为:
成员 | 对象内起始位置 | 占用字节 |
---|---|---|
__vftpr | 0 | 8 |
a | 8 | 4 |
(对齐补充) | 12 | 4 |
__vfptr存储的是A的虚表的地址,这个虚表目前只有一项,存储的是A的虚析构函数的地址~A。
为什么sizeof(A) == 16 而不是12?
因为默认情况下,编译器要保证通过数组方式访问A的成员的时候也是高效的,不管是隐式的__vfptr还是显式的a。
当按照如上所示布局的时候,读取__vfptr和a只需要一个周期。即使是访问A的数组中的成员的时候也是这样的。
但是如果按照12字节对齐,第二个A对象的__vfptr的地址就不是8字节对齐,访问__vfptr的时候,需要读取16字节,然后获取中间的8个字节。同样的汇编代码,但是系统会做更多的事情。效率自然低一些。
__vfptr是编译器在类中添加的成员,对程序员透明的。
当类中有虚函数,包括从基类继承的虚函数时,__vfptr都会存在,具体__vfptr的位置和数量跟类的继承结构有关系。