【C++】使用sizeof计算类对象所占空间大小-sizeof总结

【C++】使用sizeof计算类对象所占空间大小-sizeof总结

1.所有非静态数据成员的大小
2.数据成员的顺序
3.字节对齐或字节填充
4.其直接基类的大小虚函数的存在
5.  正在使用的编译器
6.继承模式(虚拟继承)

 

一、使用sizeof计算类对象所占空间大小

  需要注意,对类做sizeof运算时,并不是简单地把各个成员所占的内存数量相加。需要注意成员顺序不同,可能需要字节补齐。

编程实例:


 
 
  1. #include <iostream>
  2. using namespace std;
  3. class A
  4. {
  5. public:
  6. int i; //int占用4个字节
  7. };
  8. class B
  9. {
  10. public:
  11. char ch; //char占用1个字节
  12. };
  13. class C
  14. {
  15. public:
  16. int i;
  17. short j; //short占用2个字节
  18. };
  19. class D //D共占用8个字节
  20. {
  21. public:
  22. int i; //int占用4个字节
  23. short j; //short和char共占用3个字节,由于这里最宽的
  24. char ch; //基本类型是int的4个字节,再填充一个字节凑成4的倍数
  25. };
  26. class E //E共占用8个字节
  27. {
  28. public:
  29. int i;
  30. int ii; //两个int共占用8个字节
  31. short j; //1个short + 2个char = 4个字节,刚好是最宽
  32. char ch; //基本类型int的大小的整数倍,不需要再填充字节
  33. char chr;
  34. };
  35. int main()
  36. {
  37. cout << "sizeof(A) = " << sizeof(A) << endl; //4
  38. cout << "sizeof(B) = " << sizeof(B) << endl; //1
  39. cout << "sizeof(C) = " << sizeof(C) << endl; //8
  40. cout << "sizeof(D) = " << sizeof(D) << endl; //8
  41. cout << "sizeof(E) = " << sizeof(E) << endl; //12
  42. getchar();
  43. return 0;
  44. }

小结:

1.类中的数据成员顺序不同,类所占的内存大小可能不同;
2.注意需要 字节对齐或字节填充 的情况;
3.派生类的内存大小需要加上基类的内存大小。

 拓展知识:关于字节对其你和字节填充

编程实例:


 
 
  1. class C {
  2. char c;
  3. int int1;
  4. int int2;
  5. int i;
  6. long l;
  7. short s;
  8. };

 分析:

  这个类的大小是24字节。尽管char c只消耗1个字节,但将为它分配4个字节,剩下的3个字节将被浪费(留空)。这是因为下一个成员是int,它占用4个字节。如果我们不进入下一个(4)字节来存储这个整数成员,那么这个整数的内存访问/修改周期将是2个读周期。所以编译器会为我们做这个补位。

图解:

二、使用sizeof计算含有虚函数的类对象的空间大小

  虚函数的存在将在类中添加4个字节的虚拟表指针,这将被添加到类的大小。 同样,在这种情况下,如果类的基类已经直接或通过其基类具有虚函数,那么这个额外的虚函数将不会添加任何类的大小。 虚拟表指针在类层次结构中是通用的。 

编程实例:


 
 
  1. #include <iostream>
  2. using namespace std;
  3. class Base //Base占用的内存大小为4,即1个int
  4. {
  5. public:
  6. Base( int x) :a(x)
  7. {
  8. }
  9. void print() //函数不占用内存
  10. {
  11. cout << "base" << endl;
  12. }
  13. private:
  14. int a;
  15. };
  16. class Derived : public Base //Derived的内存大小=Base的大小+Derived中的一个int,
  17. { //即4 + 4 = 8
  18. public:
  19. Derived( int x) :Base(x - 1), b(x)
  20. {
  21. }
  22. void print()
  23. {
  24. cout << "derived" << endl;
  25. }
  26. private:
  27. int b;
  28. };
  29. class A //A共占用8个字节
  30. {
  31. public:
  32. A( int x) :a(x)
  33. {
  34. }
  35. virtual void print() //虚函数产生一个隐含的虚表指针成员,占4个字节
  36. {
  37. cout << "A" << endl;
  38. }
  39. private:
  40. int a; //占4个字节
  41. };
  42. class B : public A //b所占内存 = A所占内存 + 4
  43. {
  44. public:
  45. B( int x) :A(x - 1), b(x)
  46. {
  47. }
  48. virtual void print()
  49. {
  50. cout << "B" << endl;
  51. }
  52. private:
  53. int b; //占4个字节
  54. };
  55. int main()
  56. {
  57. Base obj1(1);
  58. cout << "size of Base obj is " << sizeof(obj1) << endl; //4
  59. Derived obj2(2);
  60. cout << "size of Derived obj is " << sizeof(obj2) << endl; //8
  61. A a(1);
  62. cout << "size of A obj is " << sizeof(a) << endl; //8
  63. B b(2);
  64. cout << "size of B obj is " << sizeof(b) << endl; //12
  65. getchar();
  66. return 0;
  67. }

 小结:

1.  普通函数不占用内存;
2.只要有虚函数就会占用一个指针大小的内存,原因是系统多用一个这镇维护这个类的虚函数表。

三、使用sizeof计算虚拟继承的类对象的空间大小

要点:在C++中,有时由于某些原因,我们不得不使用虚拟继承。当我们使用虚拟继承时,在该类中,虚拟基类指针将会有4个字节的开销。

编程实例:


 
 
  1. #include <iostream>
  2. using namespace std;
  3. class A //空类的大小不为零,一般来说它是1个字节,
  4. { //确保两个不同的对象具有不同的地址是非零的
  5. };
  6. class B //1个字节
  7. {
  8. };
  9. class C : public A, public B { //1个字节
  10. };
  11. class D : virtual public A { //虚函数的存在将在类中添加4个字节
  12. //的virtual table pointer
  13. };
  14. class E : virtual public A, virtual public B { //虚继承A有4个字节+
  15. //虚继承B有4个字节
  16. };
  17. class F
  18. {
  19. public:
  20. int a; //占4个字节
  21. static int b; //静态成员的空间不在类的实例中,
  22. //而是像全局变量一样在静态存储区
  23. };
  24. int F::b = 10; //在类外初始化静态成员
  25. int main()
  26. {
  27. cout << "sizeof(A) = " << sizeof(A) << endl; //1
  28. cout << "sizeof(B) = " << sizeof(B) << endl; //1
  29. cout << "sizeof(C) = " << sizeof(C) << endl; //1
  30. cout << "sizeof(D) = " << sizeof(D) << endl; //4
  31. cout << "sizeof(E) = " << sizeof(E) << endl; //8
  32. cout << "sizeof(F) = " << sizeof(F) << endl; //4
  33. getchar();
  34. return 0;
  35. }

知识扩展:为什么C ++中空类的大小不为零?

例如:


 
 
  1. #include<iostream>
  2. using namespace std;
  3. class Empty {};
  4. int main()
  5. {
  6. cout << sizeof(Empty);
  7. return 0;
  8. }

输出结果:

1

分析:

  空类的大小不为零。一般是1个字节。确保两个不同的对象具有不同的地址是非零的。

例如:


 
 
  1. #include<iostream>
  2. using namespace std;
  3. class Empty { };
  4. int main()
  5. {
  6. Empty a, b;
  7. if (&a == &b)
  8. cout << "a 和 b的地址相同 " << endl;
  9. else
  10. cout << "a 和 b的地址不同 " << endl;
  11. return 0;
  12. }

输出结果:

a 和 b的地址不同

还有另外一种情况,你可能会感到奇怪:


 
 
  1. #include<iostream>
  2. using namespace std;
  3. class Empty { };
  4. class Derived: Empty { int a; };
  5. int main()
  6. {
  7. cout << sizeof(Derived);
  8. return 0;
  9. }

 输出:

4

为什么是4,而不是5?

  原因是C++有一条规则表明空基类不需要用单独的字节表示。因此编译器可以在空基类的情况下自由优化。

<本文完> 

参考资料:

1)https://www.geeksforgeeks.org

2)https://www.cprogramming.com

3)《C和C++程序员面试秘笈》

在 C 或 C++ 中,计算一个对象所用的空间大小相对比较简单。 对于 C 语言,我们可以使用 `sizeof` 运算符来计算一个对象的大小,例如: ```c #include <stdio.h> #include <stdlib.h> int main() { int a; printf("Size of int: %ld bytes\n", sizeof(a)); return 0; } ``` 上述代码将输出 `Size of int: 4 bytes`,表示 `int` 类型所用的空间大小为 4 个字节。 对于 C++ 语言,我们同样可以使用 `sizeof` 运算符来计算一个对象的大小,例如: ```c++ #include <iostream> using namespace std; int main() { int a; cout << "Size of int: " << sizeof(a) << " bytes" << endl; return 0; } ``` 上述代码将输出 `Size of int: 4 bytes`,表示 `int` 类型所用的空间大小为 4 个字节。 需要注意的是,对于结构体和类等复杂类型的对象,其大小取决于其成员变量的类型和数量,需要逐个计算并累加,可以使用 `sizeof` 运算符和 `offsetof` 宏来计算。例如: ```c++ #include <iostream> #include <cstddef> using namespace std; struct Person { string name; int age; }; int main() { Person p; cout << "Size of Person: " << sizeof(p) << " bytes" << endl; cout << "Offset of name: " << offsetof(Person, name) << " bytes" << endl; cout << "Offset of age: " << offsetof(Person, age) << " bytes" << endl; return 0; } ``` 上述代码将输出 `Size of Person: 16 bytes`,表示 `Person` 类型所用的空间大小为 16 个字节,其中 `name` 字符串用 8 个字节,`age` 整数用 4 个字节,剩余 4 个字节为内存对齐所需的填充字节。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值