关于C++的类对象,内存分别问题.docVIP

  1. 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
  2. 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  3. 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  4. 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  5. 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  6. 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  7. 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
C/C++ 关于C++的类对象,内存分布问题--答王富涛同学 HYPERLINK /space.php?uid=39028do=blogid=6443原文出处 HYPERLINK /i_love_cpp C++对象内存布局 HYPERLINK /haoel/archive/2007/12/18/1948051.aspx C++虚函数表解释 HYPERLINK /haoel/archive/2008/10/15/3081328.aspx C++内存布局(上) HYPERLINK /haoel/archive/2008/10/15/3081385.aspx C++内存布局(下) 《深度探索 C++对象模型》 原问题如下: #include iostream using namespace std; class base { public: virtual void fun1(){}; void fun2(){}; }; int main() { base s; coutsizeof(s)endl; return 0; } 代码的结果为4。 这个我觉得是因为那个虚函数表里的一个指针占了4个字节但是如果我去掉virtual 代码的结果为1类中的普通成员函数占对象的空间吗?数据成员所占空间的计算是否也是和结构体类似呢? 这个就不明白了,请各位指点。 我的回答如下: 这个涉及到类和结构体,在C++内部的排列方式。我也不是很了解,只能就自己了解的一点知识做点回答,欢迎大家指正。 编译器在编译每个类时,不管这个类以后会实例化几个对象,首先,它会提取这些类的共性,放到一起,做成一个表。 比如类里面的非虚函数,这类函数,所有的对象共享一段函数代码,自然没有必要每个对象内部都设置一个函数指针,这太浪费内存了。因此,一个类,所有的非虚函数,会被编译器排成一个符号表,放置在特定的编译期基础变量区。这实际表现看,是放在exe文件里面的,在调用一个程序时,是直接从文件中读出,并经过地址修订,准备使用,这部分连基栈都算不上,算是常量区了,所有的常量也是放在这个区。 嗯,函数内部的静态变量,类中的静态变量,静态函数,都是这个区。 那,除掉这些,类里面还有什么呢? 还有虚函数,我们知道,虚函数表示可能继承,事实上,多次(不是多重)继承后,一个类的虚函数内部会有一个栈,每个虚函数都有一个栈,每次调用该函数,会从栈顶开始call,当然,如果程序员愿意,也可以在继承的虚函数内部,通过调用父类的同名虚函数,逐级向上call,直至call完所有的虚函数为止。 这就说明,虚函数和普通成员函数不同,每个对象都有可能变化,因此,编译器就不敢把这个函数的指针,放在常量区,必须跟着对象走,注意,不是类,类是没有实体的,因此,不存在sizeof,只有对象存在大小。(sizeof只能计算栈内存(局部变量)的大小,不能计算全局变量和动态申请(malloc)的内存大小,参考程序员面试宝典二P57和P252的笔记) 还有就是普通成员变量,这些内容,每个对象也是不一样的,因此,每个对象必须自己建立一个表来管理,否则大家就混了。 因此,我们知道了,每个类,实例化对象之后,其实对象的实体在内存中的存储,就只包含虚函数和普通成员变量,这是C++编译器为了节约内存做得优化。 我们回到你的代码看,你的代码中,fun2是普通函数,被编译器放到常量区去了,因此,不占用对象空间,虚函数fun1,则需要占用,我们知道,32位操作系统,一个指针是4Bytes,函数指针也是指针,因此,你的结果是4Bytes。取消了virtual 之后,fun1也变成了普通函数,因此和fun2等同处理,就不再占用对象空间,因此,对象空间为0了。 类的虚函数,表现为一个函数指针栈,栈底,是基类这个函数的指针,往上,实际上是继承类,该虚函数的继承函数的指针,一个类,被继承几次,比如3次,最后一次继承,这个栈就有3层。有点绕。举个例子吧 class A { virtual void Func(void); }; class B : public A { virtual void Func(void); }; class C : public B { virtual void Func(void); }; 这个A类,里面的Func指针就是它自己 B就是一个栈,栈底是A::Func,栈顶是B:Func 而C就是三层的栈了,在B的基础上,栈顶有压入了C::Func 基本上就是这个管理关系。 我的话的意思是,在任何一层继承函数,都可以去手动去call父类的对应函数,完成对整个栈链上所有函数的调用。 因为我们知道,一个类的虚函数,一旦被继承,原来的父类函数指针就被压倒栈下面去了,从栈顶看,只有最后一层的函数指针。 比如C

文档评论(0)

mhk8089 + 关注
实名认证
文档贡献者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档