读书人

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

发布时间: 2012-03-27 13:44:24 作者: rapoo

类的大小与用此类定义的对象的大小一样吗?
我在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个字节,搞不清楚原因,有人能解释下吗?

欢迎讨论!



[解决办法]
1. 类的大小和该类对象的大小始终都是一样的
2. 类中如果有了虚函数,则类对象中必须有一个指向虚函数表的指针,故大小都是4字节
去掉vritual后,该类既没有指向虚函数表的指针,又没有成员变量,本该大小为0,可是对象要在内存中必须已一定大小存在,以便区分不同对象,一般编译器都会为它分配一个字节的空间。
[解决办法]
1:
类的大小不一定等于此类定义的对象的大小,为了内存对齐编译器可能补入部分空字节。
比如:
struct A
{
char a;
int b;
}
sizeof(A)=8;//结构A的大小并不等与1+4,而是等于8.
关于内存对齐楼主可以在这个板块搜索一下,应该有很多这方面得的介绍。

2:
把virtual去掉后,没有了虚表,而且类又没有定义任何成员变量,所以这就是个空的类,但C++规定空类的大小为1,所以sizeof(myClass)=1
[解决办法]
强烈支持jxlczjp77的说法:
1:
类的大小不一定等于此类定义的对象的大小,为了内存对齐编译器可能补入部分空字节。
2:
把virtual去掉后,没有了虚表,是个空类,但C++规定空类的大小为1,所以sizeof(myClass)=1


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

我想:你们把类定义的对象和他的数据成员混起来了。如果楼主是指其数据成员,那么肯定不是数据成员大小总和。我们只能说class A; A a; sizeof(A) == sizeof(a)对所有a成立
[解决办法]
问题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)!

读书人网 >C++

热点推荐