本文标题的形式显然是非正规化的,意在说明sizeof运算符在一个类上的作用结果。主要有三点特殊情况需要注意:1、空类;2、包含static成员变量的类;3、包含虚函数的类。
一、一般情况 对于一般的类,sizeof的结果即为该类中所有成员变量所占字节数的总和,注意两点:1、内存对齐(不同操作系统,不同编译器下对齐方式不同);2、成员函数是不占据类(的对象)的存储空间的。
二、空类 空类也会占一个字节的空间。见下例:
class empty_base {
};
class derived : private empty_base{ //空白基类最优化(EBO)
private:
int mem;
};
class fuhe {
private:
int mem;
empty_base obj; //复合
};
int main(){
cout<<sizeof(empty_base)<<endl;
cout<<sizeof(derived)<<endl;
cout<<sizeof(fuhe)<<endl;
}
运行结果:
当一个类需要借助另一个类来实现是可以采用private继承,也可以采用复合,《effective C++》中给出的建议是应优先选择复合的方式(详见第三版条款39),除了一种情况:内存空间非常宝贵,则采用private继承来实现,因为这样的话,空白基类不会使得继承至它的派生类增加额外的空间,这称为EBO(empty base optimization,空白基类最优化)。
三、包含static成员变量的类 static变量保存在静态存储区,并且由该类的所有对象共享,而sizeof是针对栈或堆的。
四、包含虚函数的类 一般要包含一个指向虚函数表的指针,不同编译器的具体实现不同。见下例:
class A1 {
public:
A1(int x):m(x){ }
private:
int m;
};
class A2 {
public:
A2(int x):m(x){ }
virtual ~A2(){ }
private:
int m;
};
int main(){
cout<<sizeof(A1)<<endl;
cout<<sizeof(A2)<<endl;
}
VS2010下运行结果:
*************************************************append 2014-9-24***************************************************
为什么空类的sizeof会是一个字节呢?网上找到两种解释,比较合理:
1、既然构造了对象,那这个对象就应该确实存在于内存,应该在内存中分配独一无二的地址,否则的话,怎么区分两个不同的对象呢,尽管他们是空类的对象。因此,编译器会为空类的对象安插一个字节的空间。
2、如果空类的对象为空的话,会带来一些难以理解的麻烦。比如A是一个空类,现在有一个A的数组:A arrayA[10]; 那么语句sizeof(arrayA)/sizeof(A)就会出现除数为0的异常。