程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C >> C語言基礎知識 >> 解析c++中參數對象與局部對象的析構順序的詳解

解析c++中參數對象與局部對象的析構順序的詳解

編輯:C語言基礎知識

下面是c++的源碼:
代碼如下:

class X  {
public:
   int i;
   int j;
   ~X() {}

};
void f(X x) {
  X x1;
  x.i = 1;
  x.j = 2;

}
int main() {
    f(X());
}


下面是main函數的匯編碼:
代碼如下:

_main    PROC

; 15   : int main() {

    push    ebp
    mov    ebp, esp
    sub    esp, 8;為臨時對象預留8byte空間,由於沒有顯示定義構造函數,
              ;而且這種情況下編譯器提供無用的默認構造函數,因此看不到構造函數的調用

; 16   :     f(X());

    mov    eax, DWORD PTR $T2560[ebp+4];將偏移臨時變量的首地址4byte處內存中內容給eax,即將臨時變量的成員變量j值給eax
    push    eax;將eax壓棧
    mov    ecx, DWORD PTR $T2560[ebp];將臨時變量首地址中的內容給ecx,即將臨時變量中的成員變量i值給ecx
    push    ecx;將ecx壓棧
               ;上面四句創建了臨時變量的一份拷貝,作為參數調用f
    call    ?f@@YAXVX@@@Z                ; 調用函數f
    add    esp, 8;將棧頂指針下移8byte,釋放為參數對象的提供的棧空間
    lea    ecx, DWORD PTR $T2560[ebp];將臨時對象的首地址給ecx
    call    ??1X@@QAE@XZ                ; 為臨時對象調用析構函數

; 17   : }

    xor    eax, eax
    mov    esp, ebp
    pop    ebp
    ret    0
_main    ENDP


從上面可以看出,產生的臨時對象在函數調用完成退出後才調用析構函數。

下面是f函數的匯編碼:
代碼如下:

?f@@YAXVX@@@Z PROC                    ; f

; 9    : void f(X x) {

    push    ebp
    mov    ebp, esp
    sub    esp, 8;為局部對象x1預留8byte的空間

; 10   :   X x1;
; 11   :   x.i = 1;

    mov    DWORD PTR _x$[ebp], 1;把1寫給參數對象首地址處,即把1寫入參數對象的成員變量i

; 12   :   x.j = 2;

    mov    DWORD PTR _x$[ebp+4], 2;把2寫入偏移參數對象首地址4byte處的內存,即把2寫入參數對象的成員變量j

; 13   :    
; 14   : }

    lea    ecx, DWORD PTR _x1$[ebp];將局部變量x1的首地址給ecx
    call    ??1X@@QAE@XZ                ; 為x1調用析構函數
    lea    ecx, DWORD PTR _x$[ebp];將參數對象的首地址給ecx
    call    ??1X@@QAE@XZ                ; 為參數對象調用析構函數
    mov    esp, ebp
    pop    ebp
    ret    0
?f@@YAXVX@@@Z ENDP                    ; f
; Function compile flags: /Odtp
_TEXT    ENDS
;    COMDAT ??1X@@QAE@XZ
_TEXT    SEGMENT
_this$ = -4                        ; size = 4
??1X@@QAE@XZ PROC                    ; X::~X, COMDAT
; _this$ = ecx

; 6    :    ~X() {}

    push    ebp
    mov    ebp, esp
    push    ecx
    mov    DWORD PTR _this$[ebp], ecx
    mov    esp, ebp
    pop    ebp
    ret    0
??1X@@QAE@XZ ENDP

從上面的代碼可以看出,參數對象和局部對象都是在函數退出之前調用析構函數。並且參數對象在局部對象調用析構函數之後再調用自己的析構函數。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved