转自:http://blog.youkuaiyun.com/w_miracle/article/details/12152301
首先纠正一个错误:以前总是觉得类的大小就是sizeof(class A)的大小,直到刚才才明白是错的,我们定义了一个类,只是定义了一个类型,就像int是一样的,难道你要说int的大小的4吗,只能说int 类型的变量占4个字节。以此类推下来,只有当一个类被实例化时才会为该对象分配空间,所以sizeof(classA)是calssA 实例化对象的大小。
类的对象的大小可以由以下几部分构成:
1)非静态数据成员
2)类的继承使该类对象有了其基类的非静态数据成员
3)类的虚继承,导致在子类的对象里有一个指向基类的vtable point
4)类里有虚函数,在对象内存中会有一个虚指针指向vtable
这里有一个特殊情况:
class A
{};
sizeof(A)=??
空类对象的大小是多少???很多人都知道是 1,可是为什么是1呢?
答:在定义一个空类的对象时,系统要为该对象分配一个独一无二的确定的地址,所以系统就默认的为空类的对象的分配了1Byte的内存,以使该类的对象有确定的独一无二的地址
好,下面我们来说一下类对象的内存布局:
其实内存布局这种问题,说实话是没有正确答案的,因为它取决于编译器,下面所论均在VS2010上所执行
外加还有内存对齐所增加的字节,且派生类不会影响基类的内存对齐,不会说去占用基类因内存对齐所空出来的新增的内存。
以上就是类对象的内存布局,“[]”中的内容为可选内容
具体可将类对象的内存分配分为以下几种情况:
1)简单类,无虚函数、无继承
2)简单类,有虚函数、无继承
3)派生类、无虚函数、单继承且派生类无虚函数
4)派生类、无虚函数、多继承且派生类无虚函数
5)派生类、无虚函数、单继承且派生类有虚函数 && 派生类、无虚函数、多继承且派生类有虚函数
这里多继承情况下,有几个基类有虚函数,子类就会有多少个vptr,就是前面说的子类不会改动基类的内存布局
6)派生类、有虚函数、单继承或多继承
如果基类也有派生类,子类的虚函数地址会放在第一个基类的虚表中,不会再额外生成一张虚表
7)派生类、有虚函数、虚继承
基类存放在派生类的后面,派生类有一个vptr指向虚基类表
现在讨论类的内存布局
为什么说是讨论呢,因为我暂时还是想不通一个类的内存布局,一个类型,它没有实例化一个对象也会分配内存吗??
所以,我想应该这样理解这个问题,对于一个类来说,哪些内存是与实例化无关的,只要定义一个类就会分配的?
应该有两部分:静态成员数据、成员函数、虚表
以上几个都是属于整个类的,就是在内存中只有一份,他们存储的地方都不一样,没有内存布局可言。
虚表的存放跟平台有关,windows平台下将虚表放在常量区,linux平台下将虚表放在只读数据段中。
不知小的所见是否正确,在这里还请大牛指导