`
mmdev
  • 浏览: 12890057 次
  • 性别: Icon_minigender_1
  • 来自: 大连
文章分类
社区版块
存档分类
最新评论

C++中类对象的内存布局和占用空间

 
阅读更多
很多C++书籍中都介绍过,一个Class对象需要占用多大的内存空间。最权威的结论是:

*非静态成员变量总合。

*加上编译器为了CPU计算,作出的数据对齐处理。

*加上为了支持虚函数,产生的额外负担。

介绍完了理论知识后,再看看再找一个例子看看(注:一下所有结果都是在VC6.0 开发环境中得出的结论)

一、空类的Size

class Car

{

};

void main()

{

int size = 0;

Car objCar;

size = sizeof(objCar);

printf("%s %d /r", "Class Car Size:", size);

}

输出结果:Class Car Size:1

这是为何呢?我想对于这个问题,不仅是刚入行不久的开发新手,就算有过几年以上C++开发经验的开发人员也未必能说清楚这个。

编译器在执行Car objCar;这行代码后需要,作出一个Class Car的Object。并且这个Object的地址还是独一无二的,于是编译器就会给空类创建一个隐含的一个字节的空间。

二、只有成员变量的Size

class Car

{

private:

int nLength;

int nWidth;

};

void main()

{

int size = 0;

Car objCar;

size = sizeof(objCar);

printf("%s %d /r", "Class Car Size:", size);

}

输出结果:Class Car Size:8

这个结果很多开发人员都清楚。在32位系统中,整型变量占4个字节。这里Class Car中含有两个整型类型的成员变量,所以Class Size是8。

class Car

{

private:

int nLength;

int nWidth;

static int sHigh;

};

void main()

{

int size = 0;

Car objCar;

size = sizeof(objCar);

printf("%s %d /r", "Class Car Size:", size);

}

输出结果:Class Car Size:8

我们这次在Class Car中添加了一个静态成员变量,但是Class Size仍然是8个字节。这正好符合了,结论中的第一条:非静态成员变量总合。

class Car

{

private:

char chLogo

int nLength;

int nWidth;

static int sHigh;

};

void main()

{

int size = 0;

Car objCar;

size = sizeof(objCar);

printf("%s %d /r", "Class Car Size:", size);

}

输出结果:Class Car Size:12

在类中又插入了一个字符型变量,结果Class Size变成了12。这个就是编译器额外添加3个字符变量,做数据对齐处理,为了是提高CPU的计算速度。编译器额外添加的东西我们是无法看见的。这也符合了结论中的第二条:加上编译器为了CPU计算,作出的数据对齐处理。

既然,我们这样定义类成员数据编译器会额外的增加空。那么,我们何不在定义类的时候就考虑到数据对齐的问题,可以多定义出3个字符类型变量作为预留变量,既能满足数据对齐的要求,也给自己的程序添加了一些可扩展的空间。

三、只有成员函数的Size

class Car

{

public:

Car(){};

~Car(){};

public:

void Fun(){};

};

void main()

{

int size = 0;

Car objCar;

size = sizeof(objCar);

printf("%s %d /r", "Class Car Size:", size);

}

输出结果:Class Car Size:1

噢,这是怎么回事儿呢?再做一个实验看看。

class Car

{

public:

Car(){};

~Car(){};

public:

void Fun(){};

private:

int nLength;

int nWidth;

};

void main()

{

int size = 0;

Car objCar;

size = sizeof(objCar);

printf("%s %d /r", "Class Car Size:", size);

}

输出结果:Class Car Size:8

这次应该很清楚的了。函数是不占用类空间的。第一个例子中的Size为1个字节,正是编译器为类创建一个隐含的一个字节的空间

class Car

{

public:

Car(){};

virtual ~Car(){};

public:

void Fun(){};

};

void main()

{

int size = 0;

Car objCar;

size = sizeof(objCar);

printf("%s %d /r", "Class Car Size:", size);

}

输出结果:Class Car Size:4

这次,让析构函数为虚函数,看到了Class Size为4。这正是指向Virtual Table的指针vptr的Size。这正好符合了,结论中的第三条:加上为了支持虚函数,产生的额外负担。

到此为止,一个Class Object究竟占用多少内存空间,已经完全说清楚了。但是,这只是针对单独类,或者说是基类适用。对于子类,却不一样了。有兴趣的朋友可以做一些实验。


分享到:
评论

相关推荐

    精通Windows.API-函数、接口、编程实例.pdf

    5.1.4 虚拟内存布局、内存的分工、堆与栈 127 5.1.5 内存的保护属性和存取权限 127 5.1.6 本章API列表 127 5.2 堆管理 129 5.2.1 获取堆句柄、分配与再分配堆 129 5.2.2 获取堆中内存块的大小信息 133 ...

    精通WindowsAPI 函数 接口 编程实例

    5.1.4 虚拟内存布局、内存的分工、堆与栈 127 5.1.5 内存的保护属性和存取权限 127 5.1.6 本章API列表 127 5.2 堆管理 129 5.2.1 获取堆句柄、分配与再分配堆 129 5.2.2 获取堆中内存块的大小信息 133 ...

    asp.net知识库

    在 SQL Server 2005 中使用表值函数来实现空间数据库 SQL Server 2005的30个最重要特点 同时安装sql2000和sql2005的经验 类如何与界面绑定 在Asp.net中如何用SQLDMO来获取SQL Server中的对象信息 使用Relations建立...

    《你必须知道的495个C语言问题》

    *2.5 在C语言中是否有模拟继承等面向对象程序设计特性的好方法? 22 2.6 为什么声明extern f(struct x *p); 给我报了一个晦涩难懂的警告信息? 23 2.7 我遇到这样声明结构的代码:struct name {int namelen; ...

    C语言FAQ 常见问题列表

    o 3.5 在 C 中是否有模拟继承等面向对象程序设计特性的好方法? o 3.6 我遇到这样声明结构的代码: struct name { int namelen; char namestr[1];}; 然后又使用一些内存分配技巧使 namestr 数组用起来好像有多个...

    你必须知道的495个C语言问题

    *2.5 在C语言中是否有模拟继承等面向对象程序设计特性的好方法? 2.6 为什么声明externf(structx*p);给我报了一个晦涩难懂的警告信息? 2.7 我遇到这样声明结构的代码:structname{intnamelen;charnamestr[1];}...

    新版Android开发教程.rar

    � 采用了对有限内存、电池和 CPU 优化过的虚拟机 Dalvik , Android 的运行速度比想象的要快很多。 � 运营商(中国移动等)的大力支持,产业链条的热捧。 � 良好的盈利模式( 3/7 开),产业链条的各方:运营商、...

    你必须知道的495个C语言问题(PDF)

    2.5 在C 中是否有模拟继承等面向对象程序设计特性的好方法? . . . 7 i 目录ii 2.6 我遇到这样声明结构的代码: struct name f int namelen; char namestr[1];g; 然后又使用一些内存分配技巧使namestr 数组用起 来...

Global site tag (gtag.js) - Google Analytics