类对象所占用的内存空间

  一个类的实例化对象所占空间的大小? 注意不要说类的大小,是类的对象的大小。 首先,类的大小是什么?确切的说,类只是一个类型的定义,它是没有大小可言的,用sizeof运算符对一个类型名操做,获得的是具备该类型实体的大小ios

 1 #include <iostream>
 2 
 3 using namespace std;  4 
 5 class A  6 {  7 };  8 
 9 int main() 10 { 11  A obj; 12     int nLen = sizeof(obj); 13     cout << nLen << endl; //sizeof(一个空类)为何等于1?
14 
15     return 0; 16 }

能够看到一个空类对象的大小1.函数

一个空类对象的大小是1,为何不是0?优化

  初学者确定会很烦恼?类A明明是空类,它的大小应该为0,为何编译器输出的结果为1呢?这就是实例化的缘由(空类一样被实例化),每一个实例在内存中都有一个独一无二的地址,为了达到这个目的,编译器每每会给一个空类隐含的加一个字节,这样空类在实例化后在内存中获得了独一无二的地址,因此obj的大小是1.
spa

  

打断点调试的时候,选中obj,而后按快捷键shift+F93d

能够看到obj的地址是0x0019f77b;而后点击vs菜单栏上的窗口----内存-----内存(1)指针

而后把obj的内存地址粘贴过来:调试

 1 #include <iostream>
 2 
 3 using namespace std;  4 
 5 class A  6 {  7 public:  8     void func1() { };  9     void func2() { }; 10     void func3() { }; 11 }; 12 
13 int main() 14 { 15  A obj; 16     int nLen = sizeof(obj); 17     cout << nLen << endl; //sizeof(一个空类)为何等于1?
18 
19     return 0; 20 }

此时给类A添加了三个成员函数,此时的类A对象的大小是多少呢?code

 

咱们看到此时类A对象obj的大小仍是1,说明类的成员函数不占用类对象的内存空间对象

 

 1 #include <iostream>
 2 
 3 using namespace std;  4 
 5 class A  6 {  7 public:  8     void func1() { };  9     void func2() { }; 10     void func3() { }; 11     char ab; 12 }; 13 
14 int main() 15 { 16  A obj; 17     int nLen = sizeof(obj); 18     cout << nLen << endl; // 19 
20     obj.ab = 'c'; 21     return 0; 22 }

咱们添加了类A的成员变量ab以后,类A对象的大小是多大呢?blog

咱们看到类A对象obj的大小是1.shift+F9咱们获取到obj的内存地址

当断点走过obj.ab = 'c'这条赋值语句以后

能够看到原来0bj的内存地址上存储了63这个十六进制,而十六进制63对应的ASCII码恰好是字符c,因此说是一个字节大小。同时也说明了成员变量占用类对象的内存空间

 1 #include <iostream>
 2 
 3 using namespace std;  4 
 5 class A  6 {  7 public:  8     void func1() { };  9     void func2() { }; 10     void func3() { }; 11     //char ab;
12     int nab; 13 }; 14 
15 int main() 16 { 17  A obj; 18     int nLen = sizeof(obj); 19     cout << nLen << endl; //
20 
21     //obj.ab = 'c';
22     obj.nab = 12; 23     return 0; 24 }

输出结果为:

打断点看到obj的内存地址是0x00cff9b4。而咱们能够看到类A的成员变量是占用了4个字节来存储数据的。

 咱们再来看一个例子:

 1 #include <iostream>
 2 
 3 using namespace std;  4 
 5 class A{};  6 class B{};  7 class C : public A  8 {  9     virtual void func() = 0; 10 }; 11 
12 class D : public B, public C 13 { 14 
15 }; 16 
17 int main() 18 { 19     cout << sizeof(A) << endl; 20     cout << sizeof(B) << endl; 21 
22     cout << sizeof(C) << endl; 23     cout << sizeof(D) << endl; 24 
25     return 0; 26 }

输出结果为:

 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 class A{};
 6 class B1{};
 7 class B 
 8 {
 9     char c;
10 };
11 class C : public A 
12 {
13     virtual void func() = 0;
14 };
15 
16 class D : public B, public C {};
17 
18 class E :public B1, public C {};
19 int main()
20 {
21     cout << sizeof(A) << endl;
22     cout << sizeof(B) << endl;
23 
24     cout << sizeof(C) << endl;
25     cout << sizeof(D) << endl;
26     cout << sizeof(E) << endl;
27 
28     return 0;
29 }

输出结果:

类A,B的大小为1上面咱们已经讲过缘由,而类C是由类A派生出来的,它里面有一个纯虚函数,因为有虚函数的缘由,有一个指向虚函数的指针(vptr),在32位的系统分配给指针的大小为4个字节,因此最后获得类C的大小为4个字节(类里只要有一个虚函数,或者说至少有一个虚函数,这个类就会产生一个指向虚函数的指针,有两个虚函数就会产生两个指向虚函数的指针,类自己,指向虚函数的指针(一个或者一堆)要有地方存放,这些指针就存放在一个表格里,这个表格咱们称为“虚函数表”,这个虚函数表是保存在可执行文件中的,在程序执行的时候载入到内存中来。无论有几个虚函数,在32位的系统sizeof()都是多了4个字节)

类D的大小更让初学者疑惑,类D是由类B,C派生而来的,它的大小应该为两者之和5,为何是8呢?这是由于为了提升实例在内存中的存取效率,类的大小每每被调整到系统的整数倍,并采起就近的法则,离哪一个最近的倍数,就是该类的大小,因此类D的大小为8个字节。

下面咱们再看一个例子:

 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 class A
 6 {
 7 private:
 8     int data;
 9 };
10 
11 class B
12 {
13 private:
14     int data;
15     static int xs;
16 };
17 int B::xs = 10;
18 int main()
19 {
20     cout << sizeof(A) << endl;
21     cout << sizeof(B) << endl;
22 
23     return 0;
24 }

输出结果为:

为何类B比类A多了一个数据成员,大小却和类A的大小相同呢?由于类B的静态数据成员被编译器放在程序的一个global data members中,它是类的一个数据成员,可是它不影响类的大小,无论这个类实际产生了多少实例,仍是派生了多少新的类,静态成员在类中只有一个实体存在,而类的非静态数据成员只有被实例化的时候,他们才存在,可是类的静态数据成员一旦被声明,不管类是否被实例化,它都已经存在,能够这么说,类的静态数据成员是一种特殊的全局变量。

下面咱们看一个有构造函数,和析构函数的类的大小,它又是多大呢?

 1 #include <iostream>
 2 
 3 using namespace std;  4 
 5 class A  6 {  7 public:  8     A(int a) { x = a; }  9     void func() 10  { 11         cout << x << endl; 12  } 13 
14     ~A() { } 15 private: 16     int x; 17     int g; 18 }; 19 
20 class B 21 { 22 public: 23 private: 24     int a; 25     int b; 26     static int xs; 27 }; 28 
29 int B::xs = 20; 30 
31 int main() 32 { 33     A a(10); 34     //a.func();
35 
36  B b; 37     cout << sizeof(a) << endl; 38     cout << sizeof(b) << endl; 39     return 0; 40 }

它们的结果均相同,能够看出类的大小与它当中的构造函数,析构函数,以及其余的成员函数无关,只与它当中的成员数据有关.

 

从以上几个例子咱们能够总结出来类的大小

1.为类的非静态成员数据的类型大小之和.
2.由编译器额外加入的成员变量的大小,用来支持语言的某些特性(如:指向虚函数的指针). 
3.为了优化存取效率,进行的边缘调整(字节对齐). 
4 与类中的构造函数,析构函数以及其余的成员函数无关.

另外:一个类对象至少占用1个字节的内存空间。

相关文章
相关标签/搜索