您的位置:首页 > 编程语言 > C语言/C++

C++对象对内存的使用

2007-06-17 08:14 337 查看
我们知道,程序=代码+数据。若按照这个等式,一个C++程序在内存的中分配方式如下:
1,全局/静态变量存储区;[数据]
2,常存储区;[数据]
3,代码区;[代码]
4,栈;[数据]
5,堆;[数据]

我们写一小段代码测试一下;(Platform:winXp + vc6.0)
----------------------------------------------------------
#include <stdio.h>
#include <malloc.h>
int iGlobal;
void main()
{
static int iStatic;
char cChar = 'A';
int b = 6;
int iLocal;
int *p = new int[5];
char *c = (char*)malloc(1);

printf("iGloba address: 0x%x/n",&iGlobal);
printf("iStatic address: 0x%x/n",&iStatic);
printf("/n");
printf("a address: 0x%x/n",&cChar);
printf("cChar address: 0x%x/n",&b);
printf("iLocal address: 0x%x/n",&iLocal);
printf("p self address: 0x%x/n",&p);
printf("/n");
printf("p point address: 0x%x/n",p);
printf("c address: 0x%x/n",&(*c));
}
----------------------------------------------------------
output:
iGloba address: 0x42359c
iStatic address: 0x4235a0

a address: 0x12ff7c
cChar address: 0x12ff78
iLocal address: 0x12ff74
p self address: 0x12ff70

p point address: 0x431ed0
c address: 0x431ea0
-----------------------------------------------------------
从上面的输出可以看出:
全局/静态变量,存储在一个区域0x42659c地址;
局部变量及局部常量,存储在一个区域0x12ff70,该区域属于线程栈;(以4字节对齐).
动态创建的空间,p数组,c字符都在一个区域0x431ea0,该区域属于进程堆;(以16字节对齐).

从上面可以大体得到这样一个结论:
全局/静态变量----->全局/静态存储区;
局部变量及局部常量------>;
动态创建的内存空间------>;

有了这个基础,我们来看看C++中定义的对象的内存使用情况。我们首先定义个类:
-----------------------------------------------------------
#include <stdio.h>
class CTemp
{
public:
static int iStatic;
int a;
int b;
public:
int GetA(){return a;};
void SetA(int A){a = A;};
public:
virtual ~CTemp(){};
};
void main()
{
CTemp tm;
printf("Sizeof tm :%d/n",sizeof(tm));
CTemp tn;
printf("Sizeof tn :%d/n",sizeof(tn));
printf("tm GetA Function adress: 0x%x/n",tm.GetA);
printf("tn GetA Function adress: 0x%x/n",tn.GetA);
}
------------------------------------------------------
Output:
Sizeof tm :12
Sizeof tn :12
tm GetA Function adress: 0x40101e
tn GetA Function adress: 0x40101e
------------------------------------------------------
通过输出可以看出,tm和tn对象的大小都是12字节;
还可以看出,两个对象使用的GetA函数地址都是一样的,我们先估且认为:
1,函数不占对象的内存空间。
2,每个int 型成员占4个字节,共计12字节。

为了验证我们的假设,我们将代码更改如下:
------------------------------------------------------
#include <stdio.h>
class CTemp
{
public:
static int iStatic;
int a;
int b;
public:
int GetA(){return a;};
int GetB(){return b;};
void SetA(int A){a = A;};
void SetB(int B){b = B;};
public:
virtual ~CTemp(){};
};
void main()
{
CTemp tm;
printf("Sizeof tm :%d/n",sizeof(tm));
CTemp tn;
printf("Sizeof tn :%d/n",sizeof(tn));
}
---------------------------------------------------------
Output:
Sizeof tm :12
Sizeof tn :12
---------------------------------------------------------
通过输出可以看出,虽然增加了两个成员函数,但对象的大小并未增加。这也验证了我们的第一个假设:
成员函数并不会占用对象的内存。

再次修改我们的代码,将CTemp类的static成员变量注释掉;
//static int iStatic;
----------------------------------------------------------
Output:
Sizeof tm :12
Sizeof tn :12
----------------------------------------------------------
我们通过可以看出,对象大小并没有变化,这说明了,我们第二个假设:每个成员变量都占用了4个字节,是错误的。

修改代码验证,将int a成员注释掉;
//int a;
---------------------------------------------------------
Sizeof tm :8
Sizeof tn :8
---------------------------------------------------------
通过输出,发现对象减少了4个字节。
静态成员变量不占用对象内存。

占用内存的是a和b两个变量?不过也不对啊,两个int型变量应该占用8字节的空间,为何在每一类的输出中,一个对象占用了12字节。那么多余的4个字节是谁占用了呢?

分析下面的类:
class CTemp
{
public:
static int iStatic; [不占内存空间]
int a; [4字节]
int b; [4字节]
public:
int GetA(){return a;}; [不占内存空间]
int GetB(){return b;}; [不占内存空间]
void SetA(int A){a = A;}; [不占内存空间]
void SetB(int B){b = B;}; [不占内存空间]
public:
virtual ~CTemp(){}; [虚函数占内存空间?]
};
------------------------------------------------
虚函数占内存空间?

那我们把虚函数注释掉,再次运行我们的程序,输出如下:
----------------------------------------------
Sizeof tm :8
Sizeof tn :8
----------------------------------------------

果然是虚函数占用了内存空间,那么是一个虚函数占4字节么?

再修改代码以验证,添加一个虚函数。
virtual ~CTemp(){};
virtual void GetCount(){};
输出如下:
---------------------------------------------
Sizeof tm :12
Sizeof tn :12
---------------------------------------------
通过输出可以看出,无论多少个虚函数,只是增加了4个字节

通过以上的验证,我们可以得知,一个对象所占有的空间,主要是非静态成员数据

为什么增加了一个虚函数就是增加4个字节的空间,这是因为在每个拥有虚函数的对象,都会增加一个指向virtual table的指针,该指针本身占了4个字节且指向Virtual table。
一个类的静态数据成员,为所有该类生成的对象共享。增加新的对象,该静态成员数据所占用空间并不会随之增加。
函数的实现虽然需要占用了空间,但也不会随着对象的增加,而增加该部分占用的空间.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: