zoukankan      html  css  js  c++  java
  • C++类构造函数、析构函数运行机理

    http://blog.sina.com.cn/s/blog_6fd68d5f0100n60h.html

    前言--构造函数、析构函数的简单理解:
    1)构造函数---对象被创建时候调用的函数;
    2)析构函数---对象被释放时候调用的函数;

      案例程序源代码
    //下面的代码为一个简单的VC++6.0下生成的控制台工程,自定义了一个CObj类:
    #include "stdafx.h"
    const int BUFFER_SIZE = 1024;//常量定义,使用const类型,尽量不要使用宏定义;
    class CObj//定义类:注意尽量使用匈牙利命名法:类名以"C"为首字母,后续第一个字母大写:
    {
    public:
    CObj()//类的构造函数;
    {
    //程序中使用到的常量BUFFER_SIZE,在一个固定地方定义,方便后续维护修改;
    m_pszBuffer = new char[BUFFER_SIZE];//注意这是在堆上分配内存,使用数组分配;
    //如果分配单个字节内存为:m_pszBuffer = new char;
    };

    ~CObj()//类的析构函数
    {
    delete []m_pszBuffer;  //删除数组内存区,注意前面需要有"[]"
    };
    private:
    char *m_pszBuffer;
    };

    int main(int argc, char* argv[])
    {
    //在栈上创建对象:obj.  (区别于堆上使用new创建对象);
    CObj obj; //这一行代码在程序中运行会发生什么事情呢?Why?

        CObj *pObj;  //规范的写法应该是:CObj *pObj =NULL; //why ? 防止出现野指针!
    pObj = new CObj; //在堆上创建对象;

    printf("Hello World! ");


    delete pObj;  //释放堆上分配的对象;
    //对于栈上分配的对象obj, 程序员不用手动清除,编译器会帮我们做这个工作!
    return 0;
    }


    二 构造函数运行机理:
    1 在栈上分配对象,其构造函数会自动调用(这个过程主要靠编译程序自动编译生成其构造函数的调用代码),请看程序调试运行过程中请看:
    1)设置断点:光标移到下面代码行,然后按F9(代码左边会显示一个棕色的球,表示断点加上,再按F9可以把断点去掉);
    CObj obj; //这一行代码在程序中运行会发生什么事情呢?Why?
    2)调试运行(按F5调试运行:前提代码编译通过才可进入调试运行模式)
    3)切换到汇编模式:(在Debug工具栏上,点击“Disassembly”,切换到汇编模式,重复则切换回来源代码显示模式),显示如下:
    .....
    28:       //在栈上创建对象:obj.  (区别于堆上使用new创建对象);
    29:       CObj obj; //这一行代码在程序中运行会发生什么事情呢?Why?
    00401058   lea         ecx,[ebp-8]
    0040105B   call        @ILT+15(CObj::CObj) (00401014)   //栈上创建对象obj,会自动调用类构造函数
    ......

    30:       CObj *pObj;  //规范的写法应该是:CObj *pObj =NULL; //why ? 防止出现野指针!
     
    31:       pObj = new CObj; //在堆上创建对象;   //注:下面为该行源代码编译成的汇编代码。
    0040107C   push        8
    0040107E   call        operator new (004013c0)
    00401083   add         esp,4
    00401086   mov         dword ptr [ebp-20h],eax
    00401089   mov         byte ptr [ebp-4],1
    0040108D   cmp         dword ptr [ebp-20h],0
    00401091   je          main+60h (004010a0)
    00401093   mov         ecx,dword ptr [ebp-20h]
    00401096   call        @ILT+15(CObj::CObj) (00401014)   //堆上new创建对象,触发构造函数调用。
    0040109B   mov         dword ptr [ebp-30h],eax
    0040109E   jmp         main+67h (004010a7)
    004010A0   mov         dword ptr [ebp-30h],0
    004010A7   mov         eax,dword ptr [ebp-30h]
    004010AA   mov         dword ptr [ebp-1Ch],eax
    004010AD   mov         byte ptr [ebp-4],0
    004010B1   mov         ecx,dword ptr [ebp-1Ch]
    004010B4   mov         dword ptr [ebp-18h],ecx

    三 从以上例子可以看到
    1 在汇编模式下,可以看到:
    对象被创建过程(栈上创建临时对象,堆上分配对象)等,都会触发构造函数被自动调用(隐式调用,程序员看不到的);
    2 这一切是如何坐到的呢?  一切都是编译器在背后支持,这是C++语言实现的基本机理!

    四 关于对象的释放---析构函数
    1还是上面的案例,在调试模式下运行,请看代码:
    35:       delete pObj;  //释放堆上分配的对象---触发析构函数被调用!
    004010C4   mov         edx,dword ptr [ebp-14h]
    004010C7   mov         dword ptr [ebp-24h],edx
    004010CA   mov         eax,dword ptr [ebp-24h]
    004010CD   mov         dword ptr [ebp-20h],eax
    004010D0   cmp         dword ptr [ebp-20h],0
    004010D4   je          main+0A5h (004010e5)
    004010D6   push        1
    004010D8   mov         ecx,dword ptr [ebp-20h]
    004010DB   call        @ILT+25(CObj::`scalar deleting destructor') (0040101e)  //调用析构函数
    004010E0   mov         dword ptr [ebp-30h],eax
    004010E3   jmp         main+0ACh (004010ec)
    004010E5   mov         dword ptr [ebp-30h],0

    36:       //对于栈上分配的对象obj, 程序员不用手动清除,编译器会帮我们做这个工作!
    37:       return 0; //函数返回,触发临时对象的析构函数被调用,请看下面对应的汇编代码:
    004010F7   mov         dword ptr [ebp-2Ch],0
    004010FE   mov         dword ptr [ebp-4],0FFFFFFFFh
    00401105   lea         ecx,[ebp-14h]
    00401108   call        @ILT+10(CObj::~CObj) (0040100f)  //调用析构函数

    0040110D   mov         eax,dword ptr [ebp-2Ch]
    38:   }

    2
     总结
    因此,析构函数在对象被释放时,会被调用,注意:
    1)临时对象的释放调用,自动触发,不需要程序员处理---这一点是通过编译器来自动实现的!
    2)堆上创建的对象(new创建),需要程序员使用delete语句释放,这也是为什么每个new对象,需要有对应delete语句的原因!(这个原因与对内存的实现机理有关,后续这方面的文章会介绍)

  • 相关阅读:
    python中字典一键多相同值反转技巧
    win10下安装mysql
    上台阶问题的具体走法用python来实现
    桥接模式
    适配器模式
    多线程中lock的使用
    原型模式
    多线程
    建造者模式
    代理模式
  • 原文地址:https://www.cnblogs.com/feng9exe/p/7481410.html
Copyright © 2011-2022 走看看