空类、带构造函数、带虚函数
#include<iostream>
using namespace std;
class A
{
};
class B
{
public:B() {}~B() {}
};
class C
{
public:C() {}virtual ~C() {}
};
int main()
{cout <<"空类的大小:"<< sizeof(A) << endl; //1cout << "带构造函数和析构函数的类的大小:" << sizeof(B) << endl; //1cout << "带虚函数的类的大小:" << sizeof(C) << endl; //4return 0;}
当创建一个空类时就要创建一个地址,来标识空类的地址,编译器往往会给一个空类隐含的加一个字节,这样空类在实例化后在内存得到了独一无二的地址,所以空类所占的内存大小是1个字节。
由于构造函数和析构函数的调用与类型的实例无关(调用它们只需要知道函数地址即可),在它的实例中不需要增加任何信息。所以和空类大小相同。
存在虚函数,编译器会创建一个虚函数表,并为该类型中的每个实例中添加一个指向虚函数表的指针。32位系统下,指针大小为4。
带有成员变量的类
class D {char ch;void func() { }};class E {char ch1; //占用1字节char ch2; //占用1字节virtual void func() { }};
class F {int in;virtual void func() { }};
cout << "D类的大小"<< sizeof(D) << endl; //1
cout << "E类的大小" << sizeof(E) << endl; //8
cout << "F类的大小" << sizeof(E) << endl; //8
在计算类的大小时,和结构一样遵循内存对齐规则。
- 第一个成员在与结构体变量偏移量为0的地址处。
- 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
继承类的大小
class G :public A, public C {};
class H :public A, public B, public C {};
class I :public A, public C, public B {};cout << "G的大小" << sizeof(G) << endl; //4
cout << "H的大小" << sizeof(H) << endl; //8
cout << "I的大小" << sizeof(I) << endl; //8
当继承多个空类时
class A
{
};
class A1
{
};
class A2
{
};
class A3
{
};
class A4
{
};
class G :public A{} //sizeof(G)=1
class G :public A, public B{} //sizeof(G)=1
class G :public A, public B{} ,public A1{} //sizeof(G)=1
class G :public A, public B ,public A1, public A2{} //sizeof(G)=3class H :public A, public C, public A1, public A2, public A3, public A4, public B {};//sizeof(H)=12
class H :public A, public C, public A1, public A2, public A3, public B {};//sizeof(H)=8
大致规律就是继承多个空类时,第一个空类不占空间,每多加1个会多1。
含静态成员的类
class K {
private:int data;static int data1;
};
cout << "K的大小" << sizeof(K) << endl; //4
类K的静态数据成员被编译器放在程序的一个global data members中,它是类的一个数据成员.但是它不影响类的大小,不管这个类实际产生了多少实例,还是派生了多少新的类,静态成员数据在类中永远只有一个实体存在,而类的非静态数据成员只有被实例化的时候,他们才存在。但是类的静态数据成员一旦被声明,无论类是否被实例化,它都已存在.可以这么说,类的静态数据成员是一种特殊的全局变量。