zoukankan      html  css  js  c++  java
  • C++浅析——返回对象的函数

    一、原码分析
    1.1 测试代码

        为了方便查看拷贝构造函数调用过程,自定义了拷贝构造函数,但啥也没干。

    class CTEST
    {
    public:
            int        m_nData;
            
            //Method:
    public:
            CTEST()
            {
                    printf("0x%p CTEST is constructed
    ", this);
            }
    
            CTEST(CTEST& oCtest)
            {
                    printf("0x%p CTEST copy constructor is called, copy object from 0x%p
    ", this, &oCtest);
            }
    
            ~CTEST()
            {
                    printf("0x%p CTEST is destructed
    ", this);
            }
    };
    
    CTEST        GetCTest()
    {
            CTEST        oCtest;
    
            return        oCtest;
    }
    
    int main(int argc, char* argv[])
    {
            printf("***************************Test1***************************
    
    ");
            CTEST oTest1 = GetCTest();
            printf("oTest1 address is 0x%p
    ", &oTest1);
            printf("
    ");
            
            printf("***************************Test2***************************
    
    ");
            CTEST oTest2;
            printf("oTest2 address is 0x%p
    ", &oTest2);
            oTest2 = GetCTest();
            printf("
    ");
            
            printf("***************************Test3***************************
    
    ");
            GetCTest();
            printf("
    ");
    
            getchar();
            return 0;
    }


    运行结果


    1.2 CTEST oTest1 = GetCTest();
            用返回对象定义赋值对象时,oTest1的构造函数并不会被调用,而是传递其对象的指针作为隐含参数给GetCTest()函数,

    GetCTest()会在函数对象返回时调用其拷贝构造函数,利用返回对象对其初始化。

    1.3 oTest2 = GetCTest();
            用返回对象赋值对象时,与定义赋值不同,并不会传递其对象的指针给GetCTest()函数,而是产生了一个临时对象作为隐含参

    数传递给GetCTest()函数
    ,GetCTest()函数执行完毕后,利用临时对象给oTest2对象赋值(即浅拷贝,而不是调用其拷贝构造函数,如

    果有资源指针,可能会造成资源泄露,有兴趣的朋友可以深入研究下这个问题)。

    1.4 GetCTest();
            单独调用GetCTest()函数和1.3类似,也会产生临时对象,只是调用结束后会析构掉。

    二、深入分析
    2.1 GetCTest()反汇编分析

    7:    CTEST   GetCTest()
    8:    {
    9:        CTEST   oCtest;
    00401074   lea         ecx,[ebp-10h]
    00401077   call        @ILT+5(CTEST::CTEST) (0040100a)
    0040107C   mov         dword ptr [ebp-4],1
    10:
    11:       return  oCtest;
    00401083   lea         eax,[ebp-10h]
    00401086   push        eax                                //压入oCtest对象指针
    00401087   mov         ecx,dword ptr [ebp+8]                //取赋值对象的指针,该指针在调用GetCTest()函数时隐式传入
    0040108A   call        @ILT+20(CTEST::CTEST) (00401019)        //调用赋值对象的拷贝构造函数
    0040108F   mov         ecx,dword ptr [ebp-14h]
    00401092   or          ecx,1
    00401095   mov         dword ptr [ebp-14h],ecx
    00401098   mov         byte ptr [ebp-4],0
    0040109C   lea         ecx,[ebp-10h]
    0040109F   call        @ILT+15(CTEST::~CTEST) (00401014) //返回对象oCtest析构
    004010A4   mov         eax,dword ptr [ebp+8]                 //返回赋值对象的指针
    12:   }

           通过以上反汇编代码的分析,可以看出GetCTest()函数在调用时编译器偷偷摸摸的传入了赋值对象的指针,而返回对象的函数

    实际上在返回时已经将返回对象析构了,其返回的是赋值对象的指针,只是在析构前利用返回对象其赋值对象进行拷贝构造了。

    2.2 代码反汇编分析

    17:       CTEST oTest1 = GetCTest();
    0040123A   lea         eax,[ebp-10h]                        
    0040123D   push        eax                                //压入oTest1的指针,以供GetCTest拷贝构造对象
    0040123E   call        @ILT+0(GetCTest) (00401005)
    00401243   add         esp,4
    00401246   mov         dword ptr [ebp-4],0
    18:       printf("oTest1 address is 0x%p
    ", &oTest1);
    0040124D   lea         ecx,[ebp-10h]
    00401250   push        ecx
    00401251   push        offset string "oTest1 address is 0x%p
    " (00427164)
    00401256   call        printf (004018a0)
    0040125B   add         esp,8
    
    20:
    21:       printf("***************************Test2***************************
    
    ");
    0040126B   push        offset string "***************************Test2"... (00427114)
    00401270   call        printf (004018a0)
    00401275   add         esp,4
    22:       CTEST oTest2;
    00401278   lea         ecx,[ebp-14h]                        //调用oTest2的构造函数
    0040127B   call        @ILT+5(CTEST::CTEST) (0040100a)
    00401280   mov         byte ptr [ebp-4],1
    23:       printf("oTest2 address is 0x%p
    ", &oTest2);
    00401284   lea         edx,[ebp-14h]
    00401287   push        edx
    00401288   push        offset string "oTest2 address is 0x%p
    " (004270f8)
    0040128D   call        printf (004018a0)
    00401292   add         esp,8
    24:       oTest2 = GetCTest();
    00401295   lea         eax,[ebp-1Ch]                        //压入临时对象的指针
    00401298   push        eax
    00401299   call        @ILT+0(GetCTest) (00401005)
    0040129E   add         esp,4
    004012A1   mov         dword ptr [ebp-28h],eax                //保存GetCTest返回的对象地址到[ebp-28h]
    004012A4   mov         ecx,dword ptr [ebp-28h]
    004012A7   mov         edx,dword ptr [ecx]                //拷贝GetCTest返回的对象的m_nData参数至oTest2对象的m_nData
    004012A9   mov         dword ptr [ebp-14h],edx
    004012AC   lea         ecx,[ebp-1Ch]                        //临时对象析构
    004012AF   call        @ILT+15(CTEST::~CTEST) (00401014)
    
    26:
    27:       printf("***************************Test3***************************
    
    ");
    004012C1   push        offset string "***************************Test3"... (004270ac)
    004012C6   call        printf (004018a0)
    004012CB   add         esp,4
    28:       GetCTest();
    004012CE   lea         eax,[ebp-20h]                        //压入临时对象的指针
    004012D1   push        eax
    004012D2   call        @ILT+0(GetCTest) (00401005)
    004012D7   add         esp,4
    004012DA   lea         ecx,[ebp-20h]                        //临时对象析构
    004012DD   call        @ILT+15(CTEST::~CTEST) (00401014)


    本文为博主原创文章,如需转载请说明转至http://www.cnblogs.com/organic/
  • 相关阅读:
    message sent to deallocated instance
    将本地项目提交github
    WKWebView 初窥-JS交互探究
    抓包工具Charles的使用
    iOS hook delegate (一)
    Return
    控制方法只有相应权限才可执行
    如何模拟登陆添加了CSRF保护的网站
    HTTP客户端都应该支持的五个特性
    如何利用WebClient模拟登陆CSRF控制的网站
  • 原文地址:https://www.cnblogs.com/organic/p/5005653.html
Copyright © 2011-2022 走看看