`
蒙面考拉
  • 浏览: 155688 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

C++类对象的创建过程

 
阅读更多

分配空间(Allocation)
        创建C++类对象的第一步就是为其分配内存空间。对于全局对象,静态对象以及分配在栈区域内的对象,对它们的内存分配是在编译阶段就完成了,而对于分配在堆区域内的对象,它们的分配是在运行是动态进行的内存空间的分配过程涉及到两个关键的问题:
需要分配空间的大小,即类对象的大小。这么问题对于编译器来说并不是什么问题,因为类对象的大小就是由它决定的,对于要分配多少内存,它最清楚不过了。

         是否有足够的内存空间来满足分配。对于不同的情况我们需要具体问题具体分析:局对象和静态对象。编译器会为他们划分一个独立的段(全局段)为他们分配足够的空间,一般不会涉及到内存空间不够的问题
           分配在栈区域的对象。栈区域的大小由编译器的设置决定,不管具体的设置怎样,总归它是有一个具体的值,所以栈空间是有限的,在栈区域内同时分配超过空间大小的对象会导致栈区域溢出,由于栈区域的分配是在编译阶段完成的,所以在栈区域溢出的时候会抛出编译阶段的异常。

           分配在堆区域的对象。堆内存空间的分配是在运行是进行的,由于堆空间也是有限的,在栈区域内试图同时分配大量的对象会导致分配失败,通常情况会抛出运行时异常或者返回一个没有意义的值(通常是0)。

 

初始化(Initialization)
           这一阶段是对象创建过程中最神秘的一个阶段,也是最容易被忽视的一个阶段。要想知道这一阶段具体完成那些任务,关键是要区分两个容易混淆的概念:初始化 (Initialization)和赋值(Assignment)。初始化早于赋值,它是随着对象的诞生一起进行的。而赋值是在对象诞生以后又给予它一个新的值。这里我想到了一个很好的例子:任何一个在医院诞生的婴儿,在它诞生的同时医院会给它一个标识,以防止和其他的婴儿混淆,这个标识通常是婴儿母亲所在床铺的编号,医院给婴儿一个标识的过程可以看作是初始化。当然当婴儿的父母拿到他们会为他们起个名字,起名字的过程就可以看作是赋值经过初始化和赋值后,其他人就可以通过名字来标识他们的身份了。区分了这两个概念后,我们再转到对对象初始化的分析上。对类对象的初始化,实际上是对类对象内的所有数据成员进行初始化。C++已经为我们提供了对类对象进行初始化的能力,我们可以通过实现构造函数的初始化列表(member initialization list)来实现。具体的情况是否是这样的呢?下面我们就看看具体的情况是什么样的吧。我写了两个简单的类:

    class CInnerClass {
    public:
        CInnerClass(int id):m_iID(id) {}
        CInnerClass& operator = (const CInnerClass& rb) {
            m_iID = rb.m_iID;
            return *this;
        }
    private:
        int 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类的构造函数提供了初始化列表,用来初始化其成员变量,其相应的汇编代码如下(注:我只保留了关键的代码):

    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    DWORD PTR [eax+4], ecx

; 5    :     m_innerObj = 10;

    push    10                    ; 0000000aH
    lea    ecx, DWORD PTR $T1359[ebp]
    call   
??0CInnerClass@@QAE@H@Z            ; CInnerClass::CInnerClass
    lea    eax, DWORD PTR $T1359[ebp]
    push    eax
    mov    ecx, DWORD PTR _this$[ebp]
    call   
??4CInnerClass@@QAEAAV0@ABV0@@Z        ; CInnerClass::operator=

 

从这段汇编代码中我们可以看到一些有意义的内容:

初始化列表先于构造函数体内的代码执行;
初始化列表确实执行的是数据成员的初始化过程,这个可以从成员对象的构造函数被调用看的出来。

赋值(Assignment)
对象经过初始化以后,我们仍然可以对其进行赋值。和类对象的初始化一样,类对象的赋值实际上是对类对象内的所有数据成员进行赋值。C++也已经为我们提供了这样的能力,我们可以通过构造函数的实现体(即构造函数中由"{}"包裹的部分)来实现。这一点也可以从上面的汇编代码中成员对象的赋值操作符 (operator =)被调用得到印证。

结束
随着构造函数执行完最后一行代码,可以说类对象的创建过程也就顺利完成了。由以上的分析可以看出,构造函数实现了对象的初始化和赋值两个过程:
对象的初始化是通过初始化列表来完成,而对象的赋值则才是通过构造函数,或者更准确的说应该是构造函数的实现体

分享到:
评论

相关推荐

    COM对象创建过程总结

    COM对象创建过程总结,包括进程内和进程外的

    c++如何控制对象的创建方式(禁止创建栈对象or堆对象)和创建的数量

    通常情况下,对象创建在堆上还是在栈上,创建多少个,这都是没有限制的。但是有时会遇到一些特殊需求。 1.禁止创建栈对象 禁止创建栈对象,意味着只能在堆上创建对象。创建栈对象时会移动栈顶指针以“挪出”适当大小...

    c++类和对象的复习整理

    c++类和对象的复习整理一、类的定义二、类中的成员变量和成员函数1、成员变量2、成员函数三、创建对象四、创建类的对象指针 一、类的定义 类是创建对象的模板,一个类可以创建多个对象,每个对象都是类类型的一个...

    C++面向对象程序设计详解

    C++既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计,还可以进行以继承和多态为特点的面向对象的程序设计。C++擅长面向对象程序设计的同时,还可以进行基于过程的程序设计。 ...

    了解C++面向对象编程.rar

    C++既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计,还可以进行以继承和多态为特点的面向对象的程序设计。C++擅长面向对象程序设计的同时,还可以进行基于过程的程序设计。 ...

    C/C++在线编程过程图示

    C/C++在线编程过程图示,VC6使用过程。新手适用。

    C++习题和答案

    8. C++对C语言作了很多改进,下列描述中( )使得C语言发生了质变,即从面向过程变成为面向对象。 A.增加了一些新的运算符; B.允许函数重载,并允许设置缺省参数; C.规定函数说明必须用原型; D.引进了类和对象的...

    深度剖析C++对象池自动回收技术实现

    对象池通过对象复用的方式来避免重复创建对象,它会事先创建一定数量的对象放到池中,当用户需要创建对象的时候,直接从对象池中获取即可,用完对象之后再放回到对象池中,以便复用。这种方式避免了重复创建耗时或耗...

    详解C++编程中类的声明和对象成员的引用

    创建对象的过程也叫类的实例化。每个对象都是类的一个具体实例(Instance),拥有类的成员变量和成员函数。 与结构体一样,类只是一种复杂数据类型的声明,不占用内存空间。而对象是类这种数据类型的一个变量,占用...

    基于决策树算法的遥感影像面向对象分类软件

    决策树分类作为一种基于空间数据挖掘的知识发现的监督分类方法,它通过决策学习过程得到分类规则并对遥感影像进行分类,突破了以往分类树或分类规则的构建要利用分类者的生态学和遥感先验知识的确定。我们以AdaBoost...

    C++ 类和对象基础篇

    类是创建对象的模板,一个类可以创建多个对象,每个对象都是类类型的一个变量;创建对象的过程也叫类的实例化。每个对象都是类的一个具体实例(Instance),拥有类的成员变量和成员函数

    Visual C++实践与提高-COM和COM+篇『PDF』

    2.2 将C++对象移进DLL中——例程DB_cppdll 2.2.1 成员函数的引出 2.2.2 内存分配 2.2.3 Unicode/ASCII兼容 2.2.4 例程实现 2.2.4.1 修改接口文件 2.2.4.2 修改对象程序 2.2.4.3 修改客户程序 2.3 C++对象使用...

    C++小游戏源代码+资源合集

    C++既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计,还可以进行以继承和多态为特点的面向对象的程序设计。C++擅长面向对象程序设计的同时,还可以进行基于过程的程序设计。 ...

    C++源代码+资源合集

    C++既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计,还可以进行以继承和多态为特点的面向对象的程序设计。C++擅长面向对象程序设计的同时,还可以进行基于过程的程序设计。 ...

    C++程序设计_图书管理系统的控制台实现.pdf

    本次实验旨在主要对前期学习的有关C++面向对象部分的有关类的继承 (inheritance)相关知识的实践与应用。 在理论方面主要体现了: 1. 提升由面向过程向面向对象的思维转变; 2. 对继承关系的分析和实践应用; 3. 对函数...

    C++大学教程 光盘

    本书是一本C++编程方面的优秀教程,全面介绍了过程式编程与面向对象编程的原理与方法,细致地分析了各种性能问题、可移植性问题以及可能出错的情况。与第四版相比,本书从内容和结构上都做了较大幅度的修订与有意义...

    Visual C++ 6.0编程实例详解.part2

    6.4.2 创建CPen类对象 6.4.3 选择堆画笔 6.4.4 绘画 6.4.5 实例 6.5 画刷 6.5.1 分类 6.5.2 创建CBrush对象 6.5.3 使用逻辑画刷 6.5.4 实例 6.6 字体和文本 6.6.1 字体类型和字体...

    新手学习C++入门资料

    标准C++的iostream类库中包括了可以支持宽字符的类和对象。用wout替代cout即可。 #include iostream.h int main() { wchar_t wc; wc='b'; wout; wc='y'; wout; wc='e'; wout; return 0; } 说明一下...

    c++大学基础教程(第5版)分卷7

    《C++大学教程》(第5版)是一本C++编程方面的优秀教程,全面介绍了过程式编程与面向对象编程的原理与方法,细致地分析了各种性能问题、可移植性问题以及可能出错的情况。与第四版相比,本书从内容和结构上都做了较大...

Global site tag (gtag.js) - Google Analytics