手机
当前位置:查字典教程网 >编程开发 >C语言 >解析c++中参数对象与局部对象的析构顺序的详解
解析c++中参数对象与局部对象的析构顺序的详解
摘要:下面是c++的源码:复制代码代码如下:classX{public:inti;intj;~X(){}};voidf(Xx){Xx1;x.i=1...

下面是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

从上面的代码可以看出,参数对象和局部对象都是在函数退出之前调用析构函数。并且参数对象在局部对象调用析构函数之后再调用自己的析构函数。

【解析c++中参数对象与局部对象的析构顺序的详解】相关文章:

解决C++中重定义的方法总结

基于结构体与指针的详解

解析C++中四种强制类型转换的区别详解

C++函数返回值为对象时,构造析构函数的执行细节

c++ 成员函数与非成员函数的抉择

C语言中宏定义使用的小细节

C语言中函数与指针的应用总结

基于C/C++时间函数的使用详解

c字符串,string对象,字符串字面值的区别详解

从汇编看c++的默认析构函数的使用详解

精品推荐
分类导航