C++类所占内存大小计算
转载时请注明出处和作者联系方式 文章出处:http://blog.csdn.net/chenchong08 作者联系方式:[email protected]
说明:笔者的操作系统是32位的。
class A {}; sizeof( A ) = ? sizeof( A ) = 1 明明是空类,为什么编译器说它是1呢? 空类同样可以实例化,每个实例在内存中都有一个独一无二的地址,为了达到这个目的,编译器往往会给一个空类隐含的加一个字节,这样空类在实例化后在内存得到了独一无二的地址.所以sizeof( A )的大小为1.
class B { public: B() {} ~B() {} void MemberFuncTest( int para ) { } static void StaticMemFuncTest( int para ){ } }; sizeof( B ) = ? sizeof( B ) = 1 类的非虚成员函数是不计算在内的,不管它是否静态。
ps:成员函数还是以一般的函数一样的存在。a.fun()是通过fun(a.this)来调用的。所谓成员函数只是在名义上是类里的。其实成员函数的大小不在类的对象里面,类所占内存的大小不包括成员函数的大小,虚拟成员函数除外。同一个类的多个对象共享函数代码。而我们访问类的成员函数是通过类里面的一个指针实现,而这个指针指向的是一个table,table里面记录的各个成员函数的地址(当然不同的编译可能略有不同的实现)。所以我们访问成员函数是间接获得地址的。所以这样也就增加了一定的时间开销,这也就是为什么我们提倡把一些简短的,调用频率高的函数声明为inline形式(内联函数)。
class C { C(){} virtual ~C() {} }; sizeof( B ) = ? sizeof( B ) = 4 类D有一个虚函数,存在虚函数的类都有一个一维的虚函数表叫虚表,虚表里存放的就是虚函数的地址了,因此,虚表是属于类的。这样的类对象的前四个字节是一个指向虚表的指针,类内部必须得保存这个虚表的起始指针。在32位的系统分配给虚表指针的大小为4个字节,所以最后得到类C的大小为4.
class D { D(){} virtual ~D() {} virtual int VirtualMemFuncTest1()=0; virtual int VirtualMemFuncTest2()=0; virtual int VirtualMemFuncTest3()=0; }; sizeof( D ) = ? sizeof( D ) = 4 原理同类C,不管类里面有多少个虚函数,类内部只要保存虚表的起始地址即可,虚函数地址都可以通过偏移等算法获得。
class E { int m_Int; char m_Char; }; sizeof( E ) = ? sizeof( E ) = 8 32位的操作系统int占4个字节,char占一个字节,加上内存对齐的3字节,为8字节。
class F : public E { static int s_data ; }; int F::s_data=100; sizeof( F ) = ? sizeof( F ) = 8 类F为什么跟类E一样大呢?类F的静态数据成员被编译器放在程序的一个global data members中,它是类的一个数据成员,但是它不影响类的大小,不管这个类实际产生了多少实例还是派生了多少新的类,静态成员数据在类中永远只有一个实体存在,而类的非静态数据成员只有被实例化的时候,他们才存在.但是类的静态数据成员一旦被声明,无论类是否被实例化,它都已存在.可以这么说,类的静态数据成员是一种特殊的全局变量.
class G : public E { virtual int VirtualMemFuncTest1(int para)=0; int m_Int; }; class H : public G { int m_Int; }; sizeof( G ) = ? sizeof( H ) = ? sizeof( G ) = 16 sizeof( H ) = 20 可以看出子类的大小是本身成员的大小再加上父类成员的大小.如果父类还有父类,也加上父类的父类,这样一直递归下去。
class I : public D { virtual int VirtualMemFuncTest1()=0; virtual int VirtualMemFuncTest2()=0; }; sizeof( I ) = ? sizeof( I ) = 4 父类子类工享一个虚函数指针,虚函数指针保留一个即可。
总结: 空的类也是会占用内存空间的,而且大小是1,原因是C++要求每个实例在内存中都有独一无二的地址。 (一)类内部的成员变量: 普通的变量:是要占用内存的,但是要注意内存对齐(这点和struct类型很相似)。 static修饰的静态变量:不占用内存,原因是编译器将其放在全局变量区。 从父类继承的变量:计算进子类中 (二)类内部的成员函数: 非虚函数(构造函数、静态函数、成员函数等):不占用内存。 虚函数:要占用4个字节(32位的操作系统),用来指定虚拟函数表的入口地址。跟虚函数的个数没有关系。父类子类工享一个虚函数指针。
构成对象本身的只有数据,任何成员函数都不隶属于任何一个对象,非静态成员函数与对象的关系就是绑定,绑定的中介就是this指针。成员函数为该类所有对象共享,不仅是处于简化语言实现、节省存储的目的,而且是为了使同类对象有一致的行为。同类对象的行为虽然一致,但是操作不同的数据成员。
测试代码如下:
- <SPAN style="FONT-SIZE: 18px">
-
-
-
-
-
-
-
-
#include<iostream>
-
-
using namespace std;
-
-
class A {};
-
-
class B
- {
-
public:
- B() {}
- ~B() {}
-
void MemberFuncTest( int para ) { }
-
static void StaticMemFuncTest( int para ){ }
- };
-
-
class C
- {
- C(){}
-
virtual ~C() {}
- };
-
-
class D
- {
- D(){}
-
virtual ~D() {}
-
virtual int VirtualMemFuncTest1()=0;
-
virtual int VirtualMemFuncTest2()=0;
-
virtual int VirtualMemFuncTest3()=0;
- };
-
-
class E
- {
-
int m_Int;
-
char m_Char;
- };
-
-
class F : public E
- {
-
static int s_data ;
- };
-
int F::s_data=100;
-
-
class G : public E
- {
-
virtual int VirtualMemFuncTest1(int para)=0;
-
int m_Int;
- };
-
class H : public G
- {
-
int m_Int;
- };
-
-
class I : public D
- {
-
virtual int VirtualMemFuncTest1()=0;
-
virtual int VirtualMemFuncTest2()=0;
- };
-
-
int main( int argc, char **argv )
- {
-
cout<<"sizeof( A ) = "<<sizeof( A )<<endl;
-
cout<<"sizeof( B ) = "<<sizeof( B )<<endl;
-
cout<<"sizeof( C ) = "<<sizeof( C )<<endl;
-
cout<<"sizeof( D ) = "<<sizeof( D )<<endl;
-
cout<<"sizeof( E ) = "<<sizeof( E )<<endl;
-
cout<<"sizeof( F ) = "<<sizeof( F )<<endl;
-
cout<<"sizeof( G ) = "<<sizeof( G )<<endl;
-
cout<<"sizeof( H ) = "<<sizeof( H )<<endl;
-
cout<<"sizeof( I ) = "<<sizeof( I )<<endl;
-
-
#if defined( _WIN32 )
-
system("pause");
-
#endif
-
return 0;
- }
-
- </SPAN>
/*
* file name : main.cpp
* description : test the size of c++'s class
* create on : 2012-05-31
* create by : chenchong
* email : [email protected]
*/
#include<iostream>
using namespace std;
class A {};
class B
{
public:
B() {}
~B() {}
void MemberFuncTest( int para ) { }
static void StaticMemFuncTest( int para ){ }
};
class C
{
C(){}
virtual ~C() {}
};
class D
{
D(){}
virtual ~D() {}
virtual int VirtualMemFuncTest1()=0;
virtual int VirtualMemFuncTest2()=0;
virtual int VirtualMemFuncTest3()=0;
};
class E
{
int m_Int;
char m_Char;
};
class F : public E
{
static int s_data ;
};
int F::s_data=100;
class G : public E
{
virtual int VirtualMemFuncTest1(int para)=0;
int m_Int;
};
class H : public G
{
int m_Int;
};
class I : public D
{
virtual int VirtualMemFuncTest1()=0;
virtual int VirtualMemFuncTest2()=0;
};
int main( int argc, char **argv )
{
cout<<"sizeof( A ) = "<<sizeof( A )<<endl;
cout<<"sizeof( B ) = "<<sizeof( B )<<endl;
cout<<"sizeof( C ) = "<<sizeof( C )<<endl;
cout<<"sizeof( D ) = "<<sizeof( D )<<endl;
cout<<"sizeof( E ) = "<<sizeof( E )<<endl;
cout<<"sizeof( F ) = "<<sizeof( F )<<endl;
cout<<"sizeof( G ) = "<<sizeof( G )<<endl;
cout<<"sizeof( H ) = "<<sizeof( H )<<endl;
cout<<"sizeof( I ) = "<<sizeof( I )<<endl;
#if defined( _WIN32 )
system("pause");
#endif
return 0;
}
Windows 7 32位 VC 2010运行结果:
Linux(cent os 6.2 32位)运行结果:
|
请发表评论