当前位置:编程学习 > C/C++ >>

c++类的大小

#include<iostream>
using namespace std;
class A
{
protected:
char a;
};
class B:public A
{
protected:
char b[2];
};
class C:public A
{
protected:
char *c[3];
};
class D:public B,public C
{
protected:
char (*d)[4];
};
int main()
{
cout<<sizeof(D)<<endl;
return 0;
}


#include<iostream>
using namespace std;
class A
{
protected:
char a;
};
class B:virtual public A
{
protected:
char b[2];
};
class C:virtual public A
{
protected:
char *c[3];
};
class D:public B,public C
{
protected:
char (*d)[4];
};
int main()
{
cout<<sizeof(D)<<endl;
return 0;
}


我看了运行结果以后怎么也凑不出来,觉得好奇怪。请分析一下谢谢
答案:
#include<iostream>
using namespace std;
class A
{
protected:
char a; // 1*1=1
};
class B:public A
{
protected:
char b[2]; // 1+2*1=3
};
class C:public A
{
protected:
char *c[3]; // 4+3*4=16 其中前一个4为A对其后的大小
};
class D:public B,public C
{
protected:
char (*d)[4]; // 4+14+4=24 其中第一个4为B对其后的大小,d是个指向数组的指针,所以为4
};
int main()
{
cout<<sizeof(D)<<endl;
return 0;
}
这里要注意一下,如果程序中没有指定内存的对齐方式的话,一般的编译器是按你所声明的类或者结构体中最大的单元作为申请内存的尺度。
举个例子:
struct a
{
int a;
char b;
};
最大单元是int,size是4
那么编译器就按一次4字节申请,不够的也要补满
所以虽然char的size是1,编译器也要申请2个int所需的内存
所以sizeof(a)=8
struct a
{
double a;
char b;
};
同理,sizeof(a)=16
struct a
{
double a;
char b;
int c;
};
这个sizeof(a)仍然为16,因为char和int加起来才是5,没有用掉8字节,所以不会申请到第三个个8字节。
现在来看看你所说的
第一个:
我们先来看看D里面有什么
D里面有2个A,1个B,1个C和4个char
注意,这里所说的B和C是不算继承的A的。
这里谁最大呢?显然是C了,一个C有3个char *,大小是12
所以D申请的空间肯定是12的倍数了。
D理论上是2+2+12+4=20,所以需要12*2=24的空间,所以sizeof(D)=24
再看第二个:
用了虚基类,这样的话,B和C的继承都是虚拟的,直接导致了B和C本身的体积变大。
这里的D含有1个B,1个C,外带4个char,注意,首先要说明一下支持动态绑定的虚拟继承,
这一步骤会导致系统分配一个void型指针给A。所以A的体积是1,最小单元char的size是1,所以A申请内存1字节。
所以B的大小就是1+4(A的指针)+2=7,(这里A中的char不能和B中的char再共用内存了,详情这里情况比较复杂,详情请参考c++的教材)
B的实际大小:6+1 B申请的大小:4*3=12。
C也虚拟继承了A,所以需要内存4(A的指针)+3*4=16,外加上A本身的一个char
C的实际大小:16+1 C申请的大小:4+3*4+1*4=20
但是D,继承了两个同时虚拟继承A的类B和C,这样不用再为A中的元素再开两份内存了。
总计使用内存:A的:两个指针(B和C分别继承出来的)8+一个char1=9
B的:两个char=2
C的:3个char *=12
D的:4个char=4
加起来为18+9=27
这里最小单元是D,大小为16,所以申请内存16*2=32
所以sizeof(D)=32
在虚拟继承的机制下,内存的申请比较复杂,不是初学者一两下可以弄明白的,建议多阅读一些关于C++的VPTR的教材。

这里你可以做一个实验,在程序开头添加一句:#pragma pack(1);强制以字节对齐,不以最大的单元对齐。
你会发现,第一个的sizeof(D)就变成了20,这个应该很好理解。
第二个变成了27,这就是1个A中的char加上两个A的指针(分别存在B,C中的),再加上B,C,D自己的大小
一共1+2*4+2+12+4=27
第一个我理解是这样的:函数指针占4*4=16 + A B C的成员 char a;char b[2];char *c[3]; 因为数据对齐 所以 最后结果为    16+8 = 24
第一个:
B::A, 1B
C::A, 1B
B, 2B
C, 4 * 3 = 12B (指针数组,数组里的每一个元素指向1个char)
D, 4B (数组指针,指向一个char数组)

如果按照4字节对齐,B 和 B::A 以及C::A刚好可以共用一块4字节内存。
所以sizeof(D) = 4 + 12 + 4 = 20 字节.

第二个:
由于是虚继承,所以C::A和B::A中的a只有一份。
C::A, B::A, 1B
后面的都一样。

但是,按照4字节对齐的话,仍然是要占用20个字节。

上一个:3道C++编程
下一个:C语言又叫C++吗?

CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,