飘云阁

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 1961|回复: 1

[C/C++] 一些隐藏的临时对象

[复制链接]

该用户从未签到

发表于 2010-2-2 12:17:33 | 显示全部楼层 |阅读模式
I 当类对象传参时

//////////////////////////////////////////////////////////////////////////
//  源码
//////////////////////////////////////////////////////////////////////////

class Test
{
public:
        int m_nData;
        int m_test;
public:
        Test(int nData):m_nData(nData){}
        ~Test(){;}
public:
        void SetData(Test ttp)
        {
                m_nData = ttp.m_nData;
        }
};

void SetData(Test ttp)
{
        ;
}

int main(int argc, char* argv[])
{
        // printf("Hello World!\n");
        Test tt(10);
        tt.SetData(20);
        return 0;
}

//////////////////////////////////////////////////////////////////////////
//  简单分析
//////////////////////////////////////////////////////////////////////////

29:       Test tt(10);
004010DD   push        0Ah
004010DF   lea         ecx,[ebp-14h]
004010E2   call        @ILT+0(Test::Test) (00401005)
004010E7   mov         dword ptr [ebp-4],0
30:       tt.SetData(20);
004010EE   sub         esp,8        // 申请空间
004010F1   mov         ecx,esp
004010F3   mov         dword ptr [ebp-18h],esp
004010F6   push        14h
004010F8   call        @ILT+0(Test::Test) (00401005)          // 在这里 retn 4 只是弹出 push 14
004010FD   mov         dword ptr [ebp-20h],eax
00401100   lea         ecx,[ebp-14h]
00401103   call        @ILT+5(Test::SetData) (0040100a)     // 所以该函数中 ebp+8 就是tempobj的this指针
31:       return 0;
00401108   mov         dword ptr [ebp-1Ch],0
0040110F   mov         dword ptr [ebp-4],0FFFFFFFFh
00401116   lea         ecx,[ebp-14h]
00401119   call        @ILT+10(Test::~Test) (0040100f)
0040111E   mov         eax,dword ptr [ebp-1Ch]
32:   }


15:       void SetData(Test ttp)
16:       {
004011BA   mov         dword ptr [ebp-4],ecx
17:           m_nData = ttp.m_nData;
004011BD   mov         eax,dword ptr [ebp-4]
004011C0   mov         ecx,dword ptr [ebp+8]        // 临时对象地址
004011C3   mov         dword ptr [eax],ecx
18:       }
004011C5   lea         ecx,[ebp+8]
004011C8   call        @ILT+10(Test::~Test) (0040100f)  // 给与析构
}


当参数为对象时,先 sub esp,sizeof(obj) 申请出空间,然后进行构造再调用函数。
构造退出时,ESP既是对象的this指针,函数内ESP+8即可对临时变量进行寻址。
临时对象出函数作用域时进行析构。
PYG19周年生日快乐!

该用户从未签到

 楼主| 发表于 2010-2-2 13:08:08 | 显示全部楼层
38:       tt = GetData(30);
0040E9E8   push        1Eh
0040E9EA   lea         eax,[ebp-20h]                          // 把返回对象的地址压入堆栈
0040E9ED   push        eax
0040E9EE   call        @ILT+30(GetData) (00401023)   //
0040E9F3   add         esp,8
0040E9F6   mov         dword ptr [ebp-2Ch],eax          // 返回的临时对象
0040E9F9   mov         ecx,dword ptr [ebp-2Ch]                // 开始按位COPY
0040E9FC   mov         edx,dword ptr [ecx]
0040E9FE   mov         eax,dword ptr [ecx+4]         
0040EA01   mov         dword ptr [ebp-14h],edx
0040EA04   mov         dword ptr [ebp-10h],eax                // Copy 函数结束
0040EA07   lea         ecx,[ebp-20h]
0040EA0A   call        @ILT+10(Test::~Test) (0040100f)

// 编译器的编译原则(申请空间)
// 把函数当返回值来看待 以决定该变量所需要的空间
// 若返回值为对象 则压入的参数个数 + 1


call        @ILT+30(GetData) (00401023)
{
29:       Test temp(nData);
004010E4   mov         eax,dword ptr [ebp+0Ch]
004010E7   push        eax
004010E8   lea         ecx,[ebp-14h]                        // 局部变量的空间
004010EB   call        @ILT+0(Test::Test) (00401005)  
30:       return temp;
004010F0   mov         ecx,dword ptr [ebp+8]                  // 参数
004010F3   mov         edx,dword ptr [ebp-14h]                // 赋值(续表)
004010F6   mov         dword ptr [ecx],edx                // 赋值(m_nData)
004010F8   mov         eax,dword ptr [ebp-10h]
004010FB   mov         dword ptr [ecx+4],eax
004010FE   mov         ecx,dword ptr [ebp-18h]
00401101   or          ecx,1
00401104   mov         dword ptr [ebp-18h],ecx
00401107   lea         ecx,[ebp-14h]
0040110A   call        @ILT+10(Test::~Test) (0040100f) // 赋值OVER后 析构掉函数内部的局部对象)
0040110F   mov         eax,dword ptr [ebp+8]
31:   }
PYG19周年生日快乐!
您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

快速回复 返回顶部 返回列表