转载自:https://www.cnblogs.com/0201zcr/p/4789332.html

C/C++中不同数据类型所占用的内存大小

                     32位                 64位 

char               1                    1 

int                  4             大多数4,少数8 

short              2                    2

long               4                    8 

float               4                    4 

double            8                    8 

指针                    4                         8

(单位都为字节)

结构体(struct):比较复杂,对齐问题。

联合(union):所有成员中最长的。

枚举(enum):根据数据类型。

 

结构体sizeof

  先介绍一个相关的概念——偏移量。偏移量指的是结构体变量中成员的地址和结构体变量地址的差。结构体大小等于最后一个成员的偏移量加上最后一个成员的大小。显然,结构体变量中第一个成员的地址就是结构体变量的首地址。因此,第一个成员i的偏移量为0。第二个成员c的偏移量是第一个成员的偏移量加上第一个成员的大小(0+4),其值为4;第三个成员j的偏移量是第二个成员的偏移量加上第二个成员的大小(4+1),其值为5。

      然而,在实际中,存储变量时地址要求对齐,编译器在编译程序时会遵循两条原则

      (1)结构体变量中成员的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍) 

      (2)结构体大小必须是所有成员大小的整数倍,也即所有成员大小的公倍数。

sizeof计算嵌套的结构体大小

     对于嵌套的结构体需要将其展开。对结构体求sizeof时,上述两种原则变为:

       (1)展开后的结构体的第一个成员的偏移量应当是被展开的结构体中最大的成员的整数倍。

       (2)结构体大小必须是所有成员大小的整数倍,这里所有成员计算的是展开后的成员,而不是将嵌套的结构体当做一个整体。

类的sizeof

1空类

class A {};
1
大小为1。
类的实例化就是给每一个实例在内存中分配一块地址。空类被实例化时,会由编译器隐含的添加一个字节。所以空类的size为1。
2 虚函数

当C++类中有虚函数的时候,会有一个指向虚函数表(V-table)的指针,所有的虚函数都在这个表中。指针大小为4,所以size为4。

为了效率问题,编译器(gcc 和 微软)一般会把虚指针放在类的内存空间的最前面的位置,不管虚函数声明的位置。考虑对齐,大小都是 4 +1+1+2 = 8.

3 静态数据成员

静态数据成员被编译器放在程序的一个global data members中,它是类的一个数据成员,但不影响类的大小。不管这个类产生了多少个实例,还是派生了多少新的类,静态数据成员只有一个实例。静态数据成员,一旦被声明,就已经存在。 考虑到数据对齐, 最终是8字节。

4 普通成员函数

class A
{
public:
void fun() {};
};

大小为1。
类的大小与构造函数,析构函数,普通成员函数无关。

5 普通单继承

大小分别为4 和 8。 可以看到普通的继承就是基类的大小+派生类自身的大小。注意数据对齐。
注意:类的数据成员按其声明顺序加入内存,无访问权限无关,只看声明顺序。

6 含虚函数的单继承

7 虚单继承

8 普通多继承

9 虚函数多继承

 1 class A
 2 {
 3     virtual void fun() {}
 4 };
 5 
 6 class B
 7 {
 8     virtual void fun2() {}
 9 };
10 class C : public  A, public B
11 {
12 public:
13     virtual void fun3() {}
14 };

4 4 8

类A一个虚函数表,类B一个虚函数表,类C继承了两个虚函数表,并把自己的虚函数写在了继承顺序中第一个虚函数表中。

10 虚继承

作者:zhengjihao
来源:CSDN
原文:https://blog.csdn.net/zhengjihao/article/details/77825269
版权声明:本文为博主原创文章,转载请附上博文链接!