• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            聚星亭

            吾笨笨且懶散兮 急須改之而奮進(jìn)
            posts - 74, comments - 166, trackbacks - 0, articles - 0
              C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

                在函數(shù)調(diào)用的時(shí)候,無論是參數(shù)為對(duì)象還是返回一個(gè)對(duì)象,都將產(chǎn)生一個(gè)臨時(shí)對(duì)象。這個(gè)筆記就是為了學(xué)習(xí)這個(gè)臨時(shí)對(duì)象的產(chǎn)生過程而寫。

            本代碼的詳細(xì)例子見實(shí)例代碼Ex.01

             

            Ok,先讓我們定義一個(gè)類:

            class CExample 

            {

            public:

                   int m_nFirstNum;

                   int m_nSecNum;

             

                   int GetSum();

                   bool SetNum(int nFirst, int nSec);

                   CExample(){}                            // 空構(gòu)造,不實(shí)現(xiàn)任何功能

                   virtual ~CExample(){}                 // 空析構(gòu)

             

            };

             

            // 定義的函數(shù)實(shí)現(xiàn)部分

            int CExample::GetSum()

            {

                   return m_nFirstNum+m_nSecNum;

            }

             

             

            先讓我們看一下對(duì)象的創(chuàng)建過程

            CExample objExp1;

            //    00401393   lea         ecx,[ebp-18h]                  //  第一個(gè)對(duì)象

            //    00401396   call        @ILT+20(CExample::CExample)

            //    0040139B   mov         dword ptr [ebp-4],0              用來統(tǒng)計(jì)當(dāng)前對(duì)象個(gè)數(shù)

             

            CExample objExp2;

            //    004013A2   lea         ecx,[ebp-24h]                  //  第二個(gè)對(duì)象

            //    004013A5   call        @ILT+20(CExample::CExample)

            //    004013AA   mov         byte ptr [ebp-4],1

             

            CExample objExp3;

            //    004013AE   lea         ecx,[ebp-30h]                  //  第三個(gè)對(duì)象

            //    004013B1   call        @ILT+20(CExample::CExample)

            //    004013B6   mov         byte ptr [ebp-4],2

             

            上面創(chuàng)建了三個(gè)對(duì)象,它們的過程都非常相似,將一個(gè)局部變量地址給了ECX寄存器,然后調(diào)用構(gòu)造函數(shù)。

            先讓我們看看,構(gòu)造函數(shù)都干啥了:

            12:   CExample::CExample()

            13:   {

            00401540   push        ebp

            00401541   mov         ebp,esp

            00401543   sub         esp,44h

            00401546   push        ebx

            00401547   push        esi

            00401548   push        edi

            00401549   push        ecx                                            // 保存寄存器環(huán)境

            0040154A   lea         edi,[ebp-44h]

            0040154D   mov         ecx,11h

            00401552   mov         eax,0CCCCCCCCh

            00401557   rep stos    dword ptr [edi]

            00401559   pop         ecx                                                       // 填充完CC以后,恢復(fù)ECX內(nèi)容

            0040155A   mov         dword ptr [ebp-4],ecx

            0040155D   mov         eax,dword ptr [ebp-4]                           // 取到this指針

            00401560   mov         dword ptr [eax],offset CExample::`vftable'   // this指針指向虛表

            15:   }

            00401566   mov         eax,dword ptr [ebp-4]

            00401569   pop         edi

            0040156A   pop         esi

            0040156B   pop         ebx

            0040156C   mov         esp,ebp

            0040156E   pop         ebp

            0040156F   ret

            我們知道,我們?cè)?/span>C代碼中,實(shí)現(xiàn)的是空構(gòu)造,沒有添加任何功能,可是反匯編的時(shí)候,發(fā)現(xiàn),函數(shù)應(yīng)該有個(gè)參數(shù)(是this指針),定位虛表的時(shí)候,是又構(gòu)造完成讓this指向虛表的工作的。

             

            1、  傳遞一個(gè)對(duì)象的過程:

            bool SetExpFun(CExample objExp)

            {

                   g_objExp.SetNum(objExp.m_nFirstNum, objExp.m_nSecNum);

                   return true;

            }

                   這是我們樣例程序中,一個(gè)對(duì)象作為參數(shù)的情況。我們編寫如下的調(diào)用代碼:

                   SetExpFun(objExp1);

             

                   反匯編代碼如下:

                   004013C8   sub         esp,0Ch                                    //     申請(qǐng)臨時(shí)對(duì)象空間

                   004013CB   mov        ecx,esp                                     //     ECX指向臨時(shí)申請(qǐng)的對(duì)象

                   004013CD   mov        dword ptr [ebp-34h],esp            //   賦值一份this

                   004013D0   lea         eax,[ebp-18h]                             //   獲取第一個(gè)對(duì)象的this指針

                   004013D3   push        eax                                              //   傳遞參數(shù)

                   004013D4   call        @ILT+45(CExample::CExample)   //   使用了拷貝構(gòu)造所以有上面的參數(shù)

                   004013D9   mov        dword ptr [ebp-48h],eax             //   產(chǎn)生一個(gè)臨時(shí)對(duì)象并保存它的this指針

                   004013DC   call        @ILT+15(SetExpFun) (00401014)  //  調(diào)用函數(shù)

                   004013E1   add         esp,0Ch

             

                   上面代碼中,有兩處函數(shù)調(diào)用,一個(gè)是我們已經(jīng)非常熟悉的調(diào)用構(gòu)造函數(shù),另一個(gè)事調(diào)用我們需要的setExpFun函數(shù),當(dāng)然,通過上面的注釋,我們很容易就能知道,在這里創(chuàng)建了一個(gè)臨時(shí)的對(duì)象,而且貌似調(diào)用構(gòu)造函數(shù)的時(shí)候還傳遞了一個(gè)參數(shù)(參數(shù)是我們定義的第一個(gè)對(duì)象: objExp1)。

             

                   是的,很明顯這里是個(gè)拷貝構(gòu)造,讓我們先來看下它的調(diào)用過程。

            拷貝構(gòu)造

                   {

                          004011F0   push         ebp

                          004011F1   mov         ebp,esp

                          004011F3   sub          esp,44h

                          004011F6   push         ebx

                          004011F7   push         esi

                          004011F8   push         edi

                          004011F9   push         ecx                              ; 保存臨時(shí)對(duì)象的this指針

                          004011FA   lea          edi,[ebp-44h]

                          004011FD   mov         ecx,11h

                          00401202   mov         eax,0CCCCCCCCh

                          00401207   rep stos       dword ptr [edi]

                          00401209   pop          ecx                              ; 找到調(diào)用時(shí)傳遞的臨時(shí)對(duì)象的this指針

                          0040120A   mov         dword ptr [ebp-4],ecx

                          0040120D   mov         eax,dword ptr [ebp-4]

                          00401210   mov               ecx,dword ptr [ebp+8]   ; 參數(shù)對(duì)象的this指針,ECX中是虛表

                          00401213   mov         edx,dword ptr [ecx+4]   ; 取出參數(shù)對(duì)象的第一個(gè)成員

                          00401216   mov         dword ptr [eax+4],edx    ; 并賦值給臨時(shí)對(duì)象的第一個(gè)成員

                          00401219   mov         eax,dword ptr [ebp-4]

                          0040121C   mov         ecx,dword ptr [ebp+8]

                          0040121F   mov         edx,dword ptr [ecx+8]   ; 取到參數(shù)對(duì)象的第二個(gè)成員

                          00401222   mov         dword ptr [eax+8],edx    ; 并賦值給臨時(shí)對(duì)象的第二個(gè)成員

                          00401225   mov         eax,dword ptr [ebp-4]    ; 設(shè)置臨時(shí)對(duì)象的虛表

                          00401228   mov         dword ptr [eax],offset CExample::`vftable'

                          0040122E   mov         eax,dword ptr [ebp-4]    ; 返回一個(gè)臨時(shí)對(duì)象

                          00401231   pop          edi

                          00401232   pop          esi

                          00401233   pop          ebx

                          00401234   mov         esp,ebp

                          00401236   pop          ebp

                          00401237   ret           4

                   }

             

            從上面的代碼不難看出,我們這個(gè)拷貝構(gòu)造直接在參數(shù)中改寫的數(shù)據(jù),等出來這個(gè)函數(shù),我們main函數(shù)中:

            004013C8   sub         esp,0Ch

            申請(qǐng)的臨時(shí)對(duì)象空間中就是一個(gè)完整的對(duì)象了。

             

                   好現(xiàn)在我們繼續(xù)跟蹤調(diào)用傳參的代碼:

                   16:   bool SetExpFun(CExample objExp)

                   17:   {

                                 004012C0   push        ebp

                                 004012C1   mov        ebp,esp

                                 004012C3   push        0FFh

                                 004012C5   push        offset __ehhandler$?SetExpFun@@YA_NVCExample@@@Z

                                 004012CA   mov        eax,fs:[00000000]

                                 004012D0   push        eax

                                 004012D1   mov        dword ptr fs:[0],esp

                                 004012D8   sub         esp,44h

                                 004012DB   push        ebx

                                 004012DC   push        esi

                                 004012DD   push        edi

                                 004012DE   lea          edi,[ebp-50h]

                                 004012E1   mov         ecx,11h

                                 004012E6   mov         eax,0CCCCCCCCh

                                 004012EB   rep stos      dword ptr [edi]

                                 004012ED   mov        dword ptr [ebp-4],0                      ; 計(jì)數(shù)對(duì)象數(shù)量

                                 18:       g_objExp.SetNum(objExp.m_nFirstNum, objExp.m_nSecNum);

                                 004012F4   mov         eax,dword ptr [ebp+0Ch]                    ; 直接引用臨時(shí)對(duì)象的成員

                                 004012F7   push         eax

                                 004012F8   mov         ecx,dword ptr [ebp+10h]

                                 004012FB   push         ecx

                                 004012FC   mov         ecx,offset g_objExp                     ; 傳遞this指針

                                 00401301   call          @ILT+0(CExample::SetNum)

                                 19:       return true;

                                 00401306   mov         byte ptr [ebp-10h],1

                                 0040130A   mov         dword ptr [ebp-4],0FFFFFFFFh   ; 清空臨時(shí)對(duì)象計(jì)數(shù)

                                 00401311   lea          ecx,[ebp+8]                                  ; 取到臨時(shí)對(duì)象的this指針

                                 00401314   call         @ILT+40(CExample::~CExample)

                                 00401319   mov         al,byte ptr [ebp-10h]

                   20:   }

                   0040131C   mov         ecx,dword ptr [ebp-0Ch]

                   0040131F   mov         dword ptr fs:[0],ecx

                   00401326   pop         edi

                   00401327   pop         esi

                   00401328   pop         ebx

                   00401329   add         esp,50h

                   0040132C   cmp         ebp,esp

                   0040132E   call        __chkesp (00401610)

                   00401333   mov         esp,ebp

                   00401335   pop         ebp

                   00401336   ret

             

             

            2、  返回一個(gè)對(duì)象的過程:

            CExample GetExpFun()

            {

                   return g_objExp;

            }

             

            編寫如下的調(diào)用代碼:

                   // 下面是返回對(duì)象的情況

                   objExp2 = GetExpFun();

             

                   調(diào)試下這個(gè)程序:

            59:       objExp2 = GetExpFun();

                   004013E4   lea         ecx,[ebp-40h]           ; 返回的臨時(shí)對(duì)象空間是進(jìn)入main函數(shù)的時(shí)候,提前分配好的。

                   004013E7   push        ecx                                ;             先將對(duì)象壓棧

                   004013E8   call        @ILT+25(GetExpFun)      ;             調(diào)用函數(shù)

                          11:   CExample GetExpFun()

                          12:   {

                          00401190   push        ebp

                          00401191   mov         ebp,esp

                          00401193   sub         esp,44h

                          00401196   push        ebx

                          00401197   push        esi

                          00401198   push        edi

                          00401199   lea         edi,[ebp-44h]

                          0040119C   mov         ecx,11h

                          004011A1   mov         eax,0CCCCCCCCh

                          004011A6   rep stos    dword ptr [edi]

                          004011A8   mov         dword ptr [ebp-4],0

                          13:       return g_objExp;

                          004011AF   push        offset g_objExp (0042af80)

                          004011B4   mov         ecx,dword ptr [ebp+8]                 ; 引用傳進(jìn)來的參數(shù)對(duì)象指針

                          004011B7   call        @ILT+45(CExample::CExample)       ; 調(diào)用構(gòu)造創(chuàng)建對(duì)象

                          004011BC   mov         eax,dword ptr [ebp-4]

                          004011BF   or          al,1

                          004011C1   mov         dword ptr [ebp-4],eax                  ; 更新對(duì)象個(gè)數(shù)

                          004011C4   mov         eax,dword ptr [ebp+8]                 ; 返回……

                          14:   }

                          004011C7   pop         edi

                          004011C8   pop         esi

                          004011C9   pop         ebx

                          004011CA   add         esp,44h

                          004011CD   cmp         ebp,esp

                          004011CF   call        __chkesp

                          004011D4   mov         esp,ebp

                          004011D6   pop         ebp

                          004011D7   ret

             

                   004013ED   add         esp,4                                   

                   004013F0   mov         dword ptr [ebp-4Ch],eax                     ; 保存臨時(shí)對(duì)象的指針

                   004013F3   mov         edx,dword ptr [ebp-4Ch]

                   004013F6   mov         dword ptr [ebp-50h],edx

                   004013F9   mov         byte ptr [ebp-4],3

                   004013FD   mov         eax,dword ptr [ebp-50h]              ; 這里重載的 = 運(yùn)算符,因此將副本壓棧做復(fù)制操作

                   00401400   push        eax

                   00401401   lea         ecx,[ebp-24h]                                ; 得到第二個(gè)對(duì)象的this指針

                   00401404   call        @ILT+10(CExample::operator=)

                   00401409   mov         byte ptr [ebp-4],2

                   0040140D   lea         ecx,[ebp-40h]                                ; 使用完成,釋放臨時(shí)對(duì)象

                   00401410   call        @ILT+40(CExample::~CExample)

             

                   printf("%d\r\n", objExp2.GetSum());

             

                   OK,只要搗鼓明白了這個(gè)臨時(shí)對(duì)象,那我們的好多問題都可以解決了。

                                                         

            久久一区二区免费播放| 久久综合给合久久狠狠狠97色69| 久久国产精品久久| 久久综合一区二区无码| 亚洲国产美女精品久久久久∴| 日韩久久久久久中文人妻| 久久久青草久久久青草| 国产精品中文久久久久久久| 久久er热视频在这里精品| 久久久久久亚洲精品无码| 欧美噜噜久久久XXX| 国产精品gz久久久| 国内精品久久久人妻中文字幕| 久久青青国产| 91精品国产91久久久久久蜜臀| 亚洲中文字幕无码久久2020| 久久99精品久久久久久水蜜桃 | 亚洲&#228;v永久无码精品天堂久久 | 亚洲国产精品无码久久SM | 精品人妻久久久久久888| 久久午夜综合久久| 一本大道久久a久久精品综合| 亚洲精品高清国产一线久久| 模特私拍国产精品久久| 亚洲国产二区三区久久| 国产精品久久久久9999高清| 99久久国语露脸精品国产| 麻豆亚洲AV永久无码精品久久| 综合久久国产九一剧情麻豆| 午夜精品久久久久久久无码| 亚洲国产成人久久精品99| 久久亚洲精品无码观看不卡| 久久国产成人精品国产成人亚洲| 伊人久久大香线焦综合四虎| 久久免费美女视频| 成人亚洲欧美久久久久| 久久久久综合中文字幕| 要久久爱在线免费观看| 久久久久无码精品国产app| 亚洲国产天堂久久综合| 亚洲AV日韩精品久久久久久|