类的大小与用此类定义的对象的大小一样吗?

sujinzhao407 2007-09-10 11:33:19
我在vc6.0中做了个简单程序:

1.新定义了个类:
class myClass
{
public:
myClass();
virtual ~myClass();
protected:
private:
};

myClass::myClass()
{
}

myClass::~myClass()
{
}

2.我在main里定义了该类的对象:
myClass a;
cout << sizeof(a) << endl; //当测试类大小时替换成sizeof(myClass)
显示它们的大小都是4个字节.

3.问题1:
类的大小与用此类定义的对象的大小始终都是一样的吗? 此处是否仅仅是个巧合.
问题2:
当我把析构函数声明中的virtual去掉时大小都变成了1个字节,搞不清楚原因,有人能解释下吗?

欢迎讨论!

...全文
487 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
sujinzhao407 2007-09-11
  • 打赏
  • 举报
回复
总结一下:

1.jxlczjp77提到在结构体中内存对齐的一些知识,但内存对齐后类和对象的占的内存大小就固定了,测试也表明类(包括结构体)的大小和对象的大小仍然是一样的,不知gfxiang(afu)说的始终大小一致是否可靠,有没有高手能举出个大小不一致的反例?

2.第二个问题WinWing,gfxiang(afu)和jxlczjp77已经解释的够清楚了,也觉得很有道理.

请大家继续讨论第一个问题,看能否找出不一致的反例.谢谢大家的关注.
fish6344 2007-09-11
  • 打赏
  • 举报
回复
问题1:
类的大小与用此类定义的对象的大小始终都是一样的吗? 此处是否仅仅是个巧合.

不是巧合!设有如下类:

class Pig
{
};

则只要有如下定义:

Pig _pig;

或: Pig* _ppig = new Pig;

则所有的Pig类实例(对象)都具有相同的类型长度!这是因为编译器将按你的类声明中的数据成员分布和固定的规则(比如字节对齐)来确定该类的实例在内存中的布局!(C++语言有保证类对象原样性的责任!)

问题2:

当我把析构函数声明中的virtual去掉时大小都变成了1个字节,搞不清楚原因,有人能解释下吗?

答:
你的类声明如下:

class myClass
{
public:
myClass();
virtual ~myClass();
protected:
private:
};
你的myClass本质说是一个空类(Empty Class),一个"Empty virtual Base Class"是OOP的一个重要慨念,语言对此有规定,必须要为空类插入一个内存占位符,以在内存中有空类的不同的实例,例如:

myClass m1;
myClass m2;

其中m1与m2将分别在内存中能有不同地址。

但是这个内存占位符的大小,C++标准却没有特别的规定,因此有插入1个char(VC6.0)、有4个byte的甚至还有插入8byte(BC6.0) 的!当在你的myClass中去掉"virtual"关键字后,你的这个类就正是我们所谓的空类,因此:


class myClass
{
public:
myClass();
~myClass();
protected:
private:
};

VC6.0上的sizeof运算结果为1!

在先前未去掉"virtual"的时候,myClass类是一个典型的"Empty virtual Base Class",因此编译器为其插入了一个指向虚函数表的指针(所谓的vptr),这个指针的类型长度是4byte,因有了这4byte的指针VC省掉了那个1byte,所以先前的sizeof是4byte!这其实是VC针对空类的一个优化,有些没有此优化的编译器,可能对有virtual接口的空类sizeof运算为8byte(1个char,3byte的字节对齐,加一个vptr共计8byte)!
xure1234 2007-09-11
  • 打赏
  • 举报
回复
强烈支持jxlczjp77的说法:
1:
类的大小不一定等于此类定义的对象的大小,为了内存对齐编译器可能补入部分空字节。
2:
把virtual去掉后,没有了虚表,是个空类,但C++规定空类的大小为1,所以sizeof(myClass)=1
arong1234 2007-09-11
  • 打赏
  • 举报
回复
我想楼主问的是是否sizeof(TYPE)等于sizeof(t),如果TYPE t。这是很显然的。类的大小有啥意义?sizeof就是计算它实例的大小
NKLoveRene 2007-09-11
  • 打赏
  • 举报
回复
学习~~
jxlczjp77 2007-09-11
  • 打赏
  • 举报
回复
1:
类的大小不一定等于此类定义的对象的大小,为了内存对齐编译器可能补入部分空字节。
比如:
struct A
{
char a;
int b;
}
sizeof(A)=8;//结构A的大小并不等与1+4,而是等于8.
关于内存对齐楼主可以在这个板块搜索一下,应该有很多这方面得的介绍。

2:
把virtual去掉后,没有了虚表,而且类又没有定义任何成员变量,所以这就是个空的类,但C++规定空类的大小为1,所以sizeof(myClass)=1
xia_wu619 2007-09-11
  • 打赏
  • 举报
回复
学习中...
up
gfxiang 2007-09-11
  • 打赏
  • 举报
回复
1. 类的大小和该类对象的大小始终都是一样的
2. 类中如果有了虚函数,则类对象中必须有一个指向虚函数表的指针,故大小都是4字节
去掉vritual后,该类既没有指向虚函数表的指针,又没有成员变量,本该大小为0,可是对象要在内存中必须已一定大小存在,以便区分不同对象,一般编译器都会为它分配一个字节的空间。
WinWing 2007-09-11
  • 打赏
  • 举报
回复
虚函数需要一张虚函数表(vtb),因而需要额外的开销
arong1234 2007-09-11
  • 打赏
  • 举报
回复
另外:我楼上帖子是copy paste另外一个网友的,他说强烈支持xxx,我其实是反驳的
arong1234 2007-09-11
  • 打赏
  • 举报
回复
为什么是指针值?它又不是指针
qianlima888 2007-09-11
  • 打赏
  • 举报
回复
cout << sizeof(a) << endl;
输出的是指针值,所有Class的用sizeof都是 4!
arong1234 2007-09-11
  • 打赏
  • 举报
回复
强烈支持jxlczjp77的说法:
1:
类的大小不一定等于此类定义的对象的大小,为了内存对齐编译器可能补入部分空字节。
2:
把virtual去掉后,没有了虚表,是个空类,但C++规定空类的大小为1,所以sizeof(myClass)=1


这要看你所认为的大小是啥概念,我们没有人说是把他所有数据成员的大小加起来,而是说类的实例的大小。在这个意义上,类的大小是严格等于其实例大小的。如果有补齐,是所有实例都补齐,而不是某个实例补齐,其他不补齐

我想:你们把类定义的对象和他的数据成员混起来了。如果楼主是指其数据成员,那么肯定不是数据成员大小总和。我们只能说class A; A a; sizeof(A) == sizeof(a)对所有a成立
zyx040404 2007-09-11
  • 打赏
  • 举报
回复
如果类含有指针,在定义对象后给指针new了一下,这时大小也会不一样
virtual会有虚表
benjamin_pan 2007-09-11
  • 打赏
  • 举报
回复
gfxiang(afu)
说的完全正确,请楼主阅读c++对象模型的第三章 data语义学

64,439

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧