构造函数的调用时机(一)

构造函数是C++类的重要组成部分,起着初始化对象的作用。当对象生成的时候,编译器会自动调用对象的构造函数,完成对象的初始化工作。根据对象的不同作用域和声明周期,可以将对象分为一下几种:

1.局部对象

2.堆对象

3.全局对象

4.静态对象

下面我们将以反汇编(VC6.0)的形式,查看局部对象的调用时机

#include <stdio.h>

class CDemo
{
public:
    CDemo()
    {
        m_nInt = 100;
    }

private:
    int m_nInt;
};

int main(void)
{
    CDemo demo;     //创建一个局部对象

    return 0;
}

将代码反汇编后代码如下

16:   int main(void)
17:   {
00401020 55                   push        ebp
00401021 8B EC                mov         ebp,esp
00401023 83 EC 44             sub         esp,44h
00401026 53                   push        ebx
00401027 56                   push        esi
00401028 57                   push        edi
00401029 8D 7D BC             lea         edi,[ebp-44h]
0040102C B9 11 00 00 00       mov         ecx,11h
00401031 B8 CC CC CC CC       mov         eax,0CCCCCCCCh
00401036 F3 AB                rep stos    dword ptr [edi]
18:       CDemo demo;          //创建一个局部对象
00401038 8D 4D FC             lea         ecx,[ebp-4]            ;将this指针保存到ecx中0040103B E8 CA FF FF FF       call        @ILT+5(CDemo::CDemo) (0040100a)  ;调用对象的构造函数
19:
20:
21:       return 0;
00401040 33 C0                xor         eax,eax
22:   }
00401042 5F                   pop         edi
00401043 5E                   pop         esi
00401044 5B                   pop         ebx
00401045 83 C4 44             add         esp,44h
00401048 3B EC                cmp         ebp,esp
0040104A E8 51 00 00 00       call        __chkesp (004010a0)
0040104F 8B E5                mov         esp,ebp
00401051 5D                   pop         ebp
00401052 C3                   ret

根据反汇编代码可以看出,局部对象在创建以后,编译器会立即调用对象的构造函数。与调用一般成员函数一样,编译器会将this指针保存到ecx中,作为参数传递。继续单步进入构造函数,反汇编如下

3:    class CDemo
4:    {
5:    public:
6:        CDemo()
00401060 55                   push        ebp
00401061 8B EC                mov         ebp,esp
00401063 83 EC 44             sub         esp,44h
00401066 53                   push        ebx
00401067 56                   push        esi
00401068 57                   push        edi
00401069 51                   push        ecx      ;ecx中保存的是this指针
0040106A 8D 7D BC             lea         edi,[ebp-44h]
0040106D B9 11 00 00 00       mov         ecx,11h
00401072 B8 CC CC CC CC       mov         eax,0CCCCCCCCh
00401077 F3 AB                rep stos    dword ptr [edi]
00401079 59                   pop         ecx      ;还原ecx
0040107A 89 4D FC             mov         dword ptr [ebp-4],ecx  ;将ecx存放在一个临时变量中
7:        {
8:            m_nInt = 100;
0040107D 8B 45 FC             mov         eax,dword ptr [ebp-4]  ;将ecx传递给eax
00401080 C7 00 64 00 00 00    mov         dword ptr [eax],64h    ;相当于[this + 0],利用this指针+偏移找到第一个数据元素
9:        }
00401086 8B 45 FC             mov         eax,dword ptr [ebp-4]   ;将this指针返回
00401089 5F                   pop         edi
0040108A 5E                   pop         esi
0040108B 5B                   pop         ebx
0040108C 8B E5                mov         esp,ebp
0040108E 5D                   pop         ebp
0040108F C3                   ret

根据反汇编代码可以看出,C++语法虽然规定构造函数是没有返回值的,但是实际上编译器将this指针作为构造函数的返回值。

时间: 2024-10-13 14:36:34

构造函数的调用时机(一)的相关文章

C++拷贝构造函数的调用时机

一.拷贝构造函数调用的时机 ? 当以拷贝的方式初始化对象时会调用拷贝构造函数,这里需要注意两个关键点,分别是以拷贝的方式和初始化对象 1. 初始化对象 初始化对象是指,为对象分配内存后第一次向内存中填充数据,这个过程会调用构造函数,对象被创建后必须立即初始化.也就是说只要创建对象就会调用构造函数. 2.初始化和赋值的区别 初始化和赋值都是将数据写入内存中,从表面看,初始化在很多时候都是以复制的方式来实现的,很容易引起混淆.在定义的同时进行复制叫做初始化,定义完成以后再赋值(不管定义的时候有没有赋

[C++]复制构造函数的定义格式和调用时机

1.复制构造函数定义形式 <类名>::<复制构造函数名>(const <类名>&<对象名>) Test(const Test&t) 2.调用时机 (1)用类的已知对象定义该类的一个正在被创建的对象 Test u; Test t = u;//调用复制构造 (2)对象作为实参传递给函数形参 Test u; Test t(u); (3)对象作为函数返回值 Test u; Test fun() { Test t; return t;//调用复制构造

(copy)赋值构造函数的4种调用时机or方法

第一种调用方法: demo #include <iostream> using namespace std; class Text { public: Text() // 无参数构造函数 { m_a = 0; m_b = 0; cout << "无参数构造函数" << endl; } Text(int a) // 有参数构造函数 { m_a = a; m_b = 0; cout << "无参数构造函数" <<

【校招面试 之 C++】第4题 拷贝构造函数被调用的3个时机

1.被调用的3个时机: (1)直接初始化或拷贝初始化: (2)将一个对象作为一个实参传递,形参采用非指针或非引用的对象进行接收时: (3)函数的返回值是一个非指针或者非对象被接收时. 2.举例说明: #include <iostream> using namespace std; class Test{ private: int a; int b; static int count; public: Test(int i, int j): a(i), b(j){} void print();

sdut 3-3 构造函数的调用(高级)

3-3 构造函数的调用(高级) Time Limit: 1000MS Memory limit: 65536K 题目描述 通过本题目的练习可以掌握创建普通对象.创建对象数组和动态创建和析构对象时调用构造函数和析构函数的时机: 要求创建一个类A:类中仅包含构造函数和析构函数,按照程序的输出写出类的定义和主函数main中的代码. 输入 无 输出 输出共有11行数据,分别如示例输出所示 示例输入 无 示例输出 ----begin main--- constructing an object of A

MFC浅析(7) CWnd类虚函数的调用时机、缺省实现

CWnd类虚函数的调用时机.缺省实现 FMD(http://www.fmdstudio.net) 1. Create 2. PreCreateWindow 3. PreSubclassWindow 4. PreTranslateMessage 5. WindowProc 6. OnCommand 7. OnNotify 8. OnChildNotify 9. DefWindowProc 10. DestroyWindow 11. PostNcDestroy CWnd作为MFC中最基本的与窗口打交

多重继承,虚继承,MI继承中虚继承中构造函数的调用情况

先来测试一些普通的多重继承.其实这个是显而易见的. 测试代码: [cpp] view plain copy print? //测试多重继承中派生类的构造函数的调用顺序何时调用 //Fedora20 gcc version=4.8.2 #include <iostream> using namespace std; class base { public: base() { cout<<"base created!"<<endl; } ~base()

C++中构造函数能调用虚函数吗?(答案是语法可以,输出错误),但Java里居然可以

环境:XPSP3 VS2005 今天黑总给应聘者出了一个在C++的构造函数中调用虚函数的问题,具体的题目要比标题复杂,大体情况可以看如下的代码: [cpp] view plain copy class Base { public: Base() { Fuction(); } virtual void Fuction() { cout << "Base::Fuction" << endl; } }; class A : public Base { public:

c++中六种构造函数的实现以及9中情况下,构造函数的调用过程

六种构造函数的实现代码如下: #include<iostream> using namespace std; //c++中六种默认的构造函数 class Test { public: Test(int d = 0):m_data(d)//1构造函数(带默认值0),以参数列表的形式初始化 { cout<<"Creat Test Obj :"<<this<<endl; } ~Test()//2析构函数 { cout<<"