现在的位置: 首页 > 综合 > 正文

C++面试之类的sizeof大小

2013年08月31日 ⁄ 综合 ⁄ 共 1735字 ⁄ 字号 评论关闭

以前写过查看C++数据类型的字节数,但实际应用中我们更关心的是struct和class的大小。首先来看空类的大小,如下:

class VoidClass
{
};

运行程序,发现sizeof(VoidClass)结果为1。这里涉及到类的实例化的概念,所谓类的实例化就是在内存中分配一块地址,每个实例在内存中都有独一无二的地址。同样空类也会被实例化,所以编译器会给空类隐含的添加一个字节,这样空类实例化后就有独一无二的地址了,所以空类的sizeof为1。

再来看class非空的情况。class非空的时候,其sizeof的大小主要取决于两方面因素,一是包含元素的大小及对齐问题,二是虚函数。首先来看一下C++的对界(Alignment)问题(摘自《Effective C++》):许多计算机体系结构要求特定的类型必须放在特定的内存地址上。例如它可能会要求指针的地址必须是4倍数(four-byte aligned)或8倍数(eight-byte aligned)。如果没有奉行这个约束条件,可能导致运行期硬件异常。有些体系结构比较仁慈,没有那么霸道,而是宣称如果对界条件获得满足,便提供较佳效率。如Intel
x86体系架构上的double可被对齐于任何byte边界,但如果它是8-byte齐位,其访问速度会快许多。一般来讲,32位的C++采用8字节对界来提高运行速度,所以编译器会尽量把数据放在它的对界上以提高内存命中率。对界是可以更改的,使用

#pragma pack(x)

宏可以改变编译器的对界方式,默认是8。C++固有类型的对界取编译器对界方式与自身大小中较小的一个。例如,指定编译器按2对界,int类型的大小是4,则int的对界为2和4中较小的2。在使用默认的对界方式下,因为几乎所有的数据类型都不大于默认的对界方式8(除了long double),所以所有的固有类型的对界方式可以认为就是类型自身的大小。对于复合数据类型,如union,struct和class的对齐方式为成员中对齐方式最大的成员的对齐方式。对于下面两个类:

class ClassA
{
	char a;
	char b;
	int c;
	double d;
};

class ClassB
{
	char   a;
	double d;
	int    c;
	char   b;
};

运行程序,发现sizeof(ClassA)和sizeof(ClassB)的结果分别为1624。其对应的空间存储结构为

但也不要认为它的对齐方式就是它的大小,看下面的例子:

class Sample1
{
private:
	char a[8];
};

class Sample2
{
private:
	double b;
};

class Sample3 : public Sample1
{
private:
	char c;
};

class Sample4 : public Sample2
{
private:
	char d;
};

运行程序可以发现,它们的大小依次为8、8、9、16。虽然Sample1和Sample2大小都是8,但是Sample1的对齐方式是1,Sample是8,所以在Sample3和Sample4中才有这样的差异。
一般函数并不影响class的大小,但虚函数不是一般函数,来看看有虚函数的情况:

class BaseClass
{
public:
	BaseClass();
	virtual ~BaseClass();
private:
	char p[8];
};

class DerivedClass : public BaseClass
{
private:
	char q;
};

运行程序可以发现,它们的大小依次为12和16。可见加入虚函数后,类的结构也发生了改变,DerivedClass的大小不再像Sample3一样是9,而是16。这是因为C++类中有虚函数的时候有一个指向虚函数表的指针(vptr),在32位系统分配指针大小为4,则其对界方式也变成了4,所以才有这样的结果。

Update 2012-10-27:包含位域的sizeof计算http://blog.csdn.net/qinwang_gz/article/details/8112991

包含虚函数的sizeof计算http://blog.csdn.net/hackbuteer1/article/details/7883531

抱歉!评论已关闭.