C++在一个函数返回对象,给函数传递对象时候的处理:
一,给一个函数按值传递一个对象
1.C++给一个函数传递一个对象,若没有拷贝构造函数,则按值浅复制,此时在函数调用结束后会调用这个对象的析构函数,如果有new生成的成员,并且析构函数delete,将会导致原本的对象相应成员地址失效:
2.如果有拷贝构造函数,则调用拷贝构造函数进行复制,并且传递拷贝构造函数生成的对象:
sub esp,0x28 ; 为临时对象分配的栈空间,0x28为对象的大小
mov ecx,esp ; ecx --- esp --- 临时对象this指针
mov dword ptr ss:[ebp-0x164],esp
lea eax,dword ptr ss:[ebp-0x38]
push eax ; const Test &
call 拷贝构造函数 ; 拷贝构造函数
mov dword ptr ss:[ebp-0x19C],eax ; 临时对象this指针
call show ; 这才会调用show(t1),此时临时对象数据已经全部在堆栈上,在show(t1)便会对临时对象调用析构函数
add esp,0x28 ; 恢复为临时对象分配的栈空间
二,一个函数按值返回一个对象
首先看看这个返回对象的函数:
先初始化局部的t对象,然后调用构造函数将这个对象复制给传入的参数地址,最后调用这个t局部对象的析构函数。
一个函数将一个对象返回时会隐式的传递一个参数,它会被填充为返回对象的this指针。
如果一个函数返回一个对象,调用方则有三种情况:
1.
首先先调用构造函数生成一个对象实体,然后在调用栈中分配一段空间给函数返回临时对象(这里是[ebp-0x158])用,然后再将临时对象复制给调用方的对象实体,最后对临时对象调用析构函数。
2.
这种情况直接将调用方的对象地址当做参数传递,就不用整一个临时对象了,然后返回的对象直接就是赋值给t2,不用生成临时对象。
3.直接调用
这种便是直接传递栈上面一个地址来储存临时对象,然后函数调用完毕调用析构函数。
1.所有在GetReturn内部会调用局部对象的析构函数,一共3次调用GetReturn,所以3次析构函数调用
2.第一部分会再调用临时对象的析构函数,在整个main结束后还会调用t1的析构函数,一共2次。
3.第二部分main结束后会调用t2的析构函数,1次。
4.第三部分在GetReturn结束后会调用临时对象的析构函数,1次.。
所以整个代码一共会调用7次(3+2+1+1)析构函数: