一直不明白c++中类中的函数和成员变量在实例化对象后在内存中究竟是个什么样的布局。一度以为一个对象的内存布局应该包括函数体和成员变量,后来才知道对象的内存布局是不包括函数体的。也就是说实例化一个类后,该对象占用的内存空间大小实际上是它的成员变量在内存中所占用空间大小(注意,含有静态成员变量和虚函数的类对象例外)。以下分析以下c++类对象在内存中的布局,并且探讨在给定一个类的成员变量的类型和数量时,如何使得类实例化后对象所占用的内存空间最小(考虑变量在内存中对齐)。
先给出一个类,如下:
1 class A
2 {
3 public:
4 A()
5 {
6 cout << "A" << endl;
7 }
8 virtual ~A()
9 {
10 cout << "~A" << endl;
11 }
12 virtual void printA()
13 {
14 cout << "printA" << endl;
15 }
16 private:
17
18 int a;
19 char c;
20 char e;
21 double b;
22 static double d;
23 };
24
25 int main()
26 {
27
28 A a;
29 cout << sizeof(a) << endl; //输出是24
30 return 0;
31 }
以上代码输出是:24。也就是说对象a占用内存空间大小是24字节,这个24字节是怎么得来的呢?我们注意到在类A中存在虚函数,而只有类中有虚函数存在,则可以知道,在每个类对象占用内存空间的首部都会有一个虚函数表,这个虚函数表可以看成是一个指针数组,在对象a中虚函数表中总共有2项,因为类A中存在两个虚函数,每个虚函数都在虚函数表中有一个项对应。现在我们知道虚函数表是2个指针的内存大小,所以是2*4=8字节。然后a,c,e总共占用4+1+1=6字节,由于需要进行内存对齐,所以实际上它占用的大小是8字节(即类对象中的内存按照占用内存空间最大的变量来对齐,static变量不考虑在内)。然后是b占用8字节,static变量d不占用空间,综上对象a占用空间大小为8(虚函数表)+8(a,c,e)+8(b)=24字节。具体可以在vs下调试,查看a的地址。
由于要考虑到内存对齐,所以。。今天有事,以后待续