首先举一个例子:
若char是一字节,int是4字节,指针类型是4字节,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
class
CTest { public : CTest():m_chData(‘\0’),m_nData(0) { } virtual
void
mem_fun(){} private : char
m_chData; int
m_nData; static
char
s_chData; }; char
CTest::s_chData=’\0’; |
问:
(1)若按4字节对齐sizeof(CTest)的值是多少?
(2)若按1字节对齐sizeof(CTest)的值是多少?
请选择正确的答案。
-
16 4
-
16 10
-
12 9 (正确答案)
-
10 10
分析:
(1)在类中,如果什么都没有,则类占用一个字节,一旦类中有其它成员,则这个字节就不在计算之类,例如如果一个类含有一个int类型,则占用4个字节而非5个字节。
(2)如果只有成员函数,则还是只占一个字节,因为类函数不占用空间。
(3)sizeof的本质是得到某个类型的大小,就是创建这个类型的一个对象(或变量)时,需要为其分配空间的大小。而类也可以理解为int或float这样的一种类型。当出现static成员变量的时候,静态成员是存储在静态存储区中的,它是一个共享的量,所以是这个类实例对象时无需再为static成员变量分配空间的。
(4)类中一旦有virtual修饰的成员函数,编译器会构建虚函数表,在该类中会存放一个指向虚函数表的指针,在
32位机中该指针和其他指针一样占用4字节。
若按4字节对齐sizeof(CTest)的值:
虚函数表 占一个指针的空间 4 即virtualvoidmem_fun(){}
char
m_chData;
1 + 3 对齐 4
int m_nData;
4
总共:12
若按1字节对齐sizeof(CTest)的值: char
m_chData; 1 已经对齐,其它不变,所以是9。
总结:1.类中一旦有virtual修饰的成员函数,编译器会构建虚函数表,在该类中会存放一个指向虚函数表的指针,在
32位机中该指针和其他指针一样占用4字节。
2.static作为静态变量是对类而言的,为所有对象共有,不计算对象的占用空间。
3.神马都没有或仅有非虚成员函数的类或仅有类型声明的类(如typdef),均为空类。对于空类,编译器会构造占用1字节空间的变量(通常为char型);
若该类为基类,则继承自空基类的子类不计算这1字节的空间,仅计算子类所占空间(编译器原理:空基类优化)。
4.对齐规则,如果注意了题目说明或代码开头的字节对齐宏:#pragma pack