欢迎来到天天文库
浏览记录
ID:59554634
大小:26.50 KB
页数:5页
时间:2020-11-10
《C++类对象创建过程.doc》由会员上传分享,免费在线阅读,更多相关内容在教育资源-天天文库。
1、C++类对象创建过程揭密分类: Linux开发c/c++2007-08-0408:18 654人阅读 评论(1) 收藏 举报介绍初看到这个题目,你可能会有些疑惑:C++类对象的创建还有什么好说的,不就是调用构造函数么?实际上情况并不是想象中的那么简单,大量的细节被隐藏或者被忽略了,而这些细节又是解决一些其他问题的关键,所以我们很有必要深入到这块"神秘"的区域,去探索鲜为人知的秘密。 分配空间(Allocation)创建C++类对象的第一步就是为其分配内存空间。对于全局对象,静态对象以及分配在栈区域内的对象,对它们的内存分配是在编译阶段就完成了,而对于分配在堆区域内
2、的对象,它们的分配是在运行是动态进行的。内存空间的分配过程涉及到两个关键的问题:·需要分配空间的大小,即类对象的大小。这么问题对于编译器来说并不是什么问题,因为类对象的大小就是由它决定的,对于要分配多少内存,它最清楚不过了。·是否有足够的内存空间来满足分配。对于不同的情况我们需要具体问题具体分析:o全局对象和静态对象。编译器会为他们划分一个独立的段(全局段)为他们分配足够的空间,一般不会涉及到内存空间不够的问题。o分配在栈区域的对象。栈区域的大小由编译器的设置决定,不管具体的设置怎样,总归它是有一个具体的值,所以栈空间是有限的,在栈区域内同时分配大量的对象会导致栈
3、区域溢出,由于栈区域的分配是在编译阶段完成的,所以在栈区域溢出的时候会抛出编译阶段的异常。o分配在堆区域的对象。堆内存空间的分配是在运行是进行的,由于堆空间也是有限的,在栈区域内试图同时分配大量的对象会导致导致分配失败,通常情况会抛出运行时异常或者返回一个没有意义的值(通常是0)。初始化(Initialization)这一阶段是对象创建过程中最神秘的一个阶段,也是最容易被忽视的一个阶段。要想知道这一阶段具体完成那些任务,关键是要区分两个容易混淆的概念:初始化(Initialization)和赋值(Assignment)。初始化早于赋值,它是随着对象的诞生一起进行的
4、。而赋值是在对象诞生以后又给予它一个新的值。这里我想到了一个很好的例子:任何一个在医院诞生的婴儿,在它诞生的同时医院会给它一个标识,以防止和其他的婴儿混淆,这个标识通常是婴儿母亲所在床铺的编号,医院给婴儿一个标识的过程可以看作是初始化。当然当婴儿的父母拿到他们会为他们起个名字,起名字的过程就可以看作是赋值。经过初始化和赋值后,其他人就可以通过名字来标识他们的身份了。区分了这两个概念后,我们再转到对对象初始化的分析上。对类对象的初始化,实际上是对类对象内的所有数据成员进行初始化。C++已经为我们提供了对类对象进行初始化的能力,我们可以通过实现构造函数的初始化列表(m
5、emberinitializationlist)来实现。具体的情况是否是这样的呢?下面我们就看看具体的情况是什么样的吧。我写了两个简单的类: class CInnerClass { public: CInnerClass(int id):m_iID(id) {} CInnerClass& operator = (const CInnerClass& rb) { m_iID = rb.m_iID; return *this; } private: i
6、nt m_iID; }; class CJdBase { public: CJdBase::CJdBase(int id):m_innerObj(id),m_iID(id){ m_innerObj = 10; } private: CInnerClass m_innerObj; int m_iID; };我们重点是看看CJdBase类的构造函数。CJdBase类的构造函数提供了初始化列表,用来初始化其成员变量,其相应的汇编代码如下(注:我只保留了关键
7、的代码): mov DWORD PTR _this$[ebp], ecx mov eax, DWORD PTR _id$[ebp] push eax mov ecx, DWORD PTR _this$[ebp] call ??0CInnerClass@@QAE@H@Z ; CInnerClass::CInnerClass mov eax, DWORD PTR _this$[ebp] mov ecx, DWORD PTR _id$[ebp] mov
8、DWORD
此文档下载收益归作者所有