1.局部对象
CNumber Number;
00408F7D 8D 4D EC lea ecx,[Number] ;this指针的来源 对象的首地址
00408F80 E8 AA B0 FF FF call CNumber::CNumber (040402Fh) ;调用构造函数 先到跳转表
CNumber()
;栈操作
00408900 55 push ebp
00408901 8B EC mov ebp,esp
00408903 81 EC CC 00 00 00 sub esp,0CCh
00408909 53 push ebx
0040890A 56 push esi
0040890B 57 push edi
0040890C 51 push ecx
0040890D 8D BD 34 FF FF FF lea edi,[ebp-0CCh]
00408913 B9 33 00 00 00 mov ecx,33h
00408918 B8 CC CC CC CC mov eax,0CCCCCCCCh
0040891D F3 AB rep stos dword ptr es:[edi]
;主体部分
0040891F 59 pop ecx
00408920 89 4D F8 mov dword ptr [this],ecx ;this指针始出面
{
m_nNumber = 1;
00408923 8B 45 F8 mov eax,dword ptr [this]
00408926 C7 00 01 00 00 00 mov dword ptr [eax],1 ;这就很奇怪了哈 这是绕了两个弯啊 特征无疑
}
0040892C 8B 45 F8 mov eax,dword ptr [this] ;还有这里 完全是程式化的多此一举
0040892F 5F pop edi
00408930 5E pop esi
00408931 5B pop ebx
00408932 8B E5 mov esp,ebp
00408934 5D pop ebp
00408935 C3 ret
2.堆对象
CNumber * pNumber = NULL;
00408F7D C7 45 EC 00 00 00 00 mov dword ptr [pNumber],0
pNumber = new CNumber[4];
00408F84 6A 14 push 14h ;类的大小
00408F86 E8 F8 A7 FF FF call operator new[] (0403783h)
00408F8B 83 C4 04 add esp,4
00408F8E 89 85 FC FE FF FF mov dword ptr [ebp-104h],eax ;保存new返回值的临时变量
00408F94 C7 45 FC 00 00 00 00 mov dword ptr [ebp-4],0 ;保存申请空间的次数
00408F9B 83 BD FC FE FF FF 00 cmp dword ptr [ebp-104h],0 ;判断堆空间是否申请成功
00408FA2 74 3A je main+9Eh (0408FDEh) ;失败则跳过构造函数
;构造函数
00408FA4 8B 85 FC FE FF FF mov eax,dword ptr [ebp-104h]
00408FAA C7 00 04 00 00 00 mov dword ptr [eax],4
00408FB0 68 9B 3D 40 00 push offset CNumber::~CNumber (0403D9Bh)
00408FB5 68 2F 40 40 00 push offset CNumber::CNumber (040402Fh)
00408FBA 6A 04 push 4
00408FBC 6A 04 push 4
00408FBE 8B 8D FC FE FF FF mov ecx,dword ptr [ebp-104h]
00408FC4 83 C1 04 add ecx,4
00408FC7 51 push ecx
00408FC8 E8 9C 8F FF FF call `eh vector constructor iterator' (0401F69h)
;堆对象代理函数
; eh vector constructor iterator(pArrayAddress, sizeof(object), object_count,
;pFunConstructor, pFunDestructor)其中 pFunDestructor为析构函数, pFunConstructor为构造函数,
;object_count为对象数量, sizeof(object)为对象大小,pArrayAddress为起始地址。5个参数的函数并不多啊
00408FCD 8B 95 FC FE FF FF mov edx,dword ptr [ebp-104h] ;this指针
00408FD3 83 C2 04 add edx,4
00408FD6 89 95 C4 FE FF FF mov dword ptr [ebp-13Ch],edx
00408FDC EB 0A jmp main+0A8h (0408FE8h)
;申请堆空间失败
00408FDE C7 85 C4 FE FF FF 00 00 00 00 mov dword ptr [ebp-13Ch],0
;this指针倒啊倒
00408FE8 8B 85 C4 FE FF FF mov eax,dword ptr [ebp-13Ch] ;this指针
00408FEE 89 85 08 FF FF FF mov dword ptr [ebp-0F8h],eax
00408FF4 C7 45 FC FF FF FF FF mov dword ptr [ebp-4],0FFFFFFFFh
00408FFB 8B 8D 08 FF FF FF mov ecx,dword ptr [ebp-0F8h]
00409001 89 4D EC mov dword ptr [pNumber],ecx
pNumber->m_nNumber = 2;
00409004 8B 45 EC mov eax,dword ptr [pNumber] ;一个this指针传出花来了
00409007 C7 00 02 00 00 00 mov dword ptr [eax],2
printf("%d \r\n", pNumber->m_nNumber);
0040900D 8B 45 EC mov eax,dword ptr [pNumber]
00409010 8B 08 mov ecx,dword ptr [eax]
00409012 51 push ecx
00409013 68 14 C0 49 00 push offset string "%d \r\n" (049C014h)
00409018 E8 9C AD FF FF call _printf (0403DB9h)
0040901D 83 C4 08 add esp,8
3.参数对象:
1.浅拷贝:如没有定义拷贝构造函数,编译器会对原对象与拷贝对象中的各数据成员直接进行数据复制,称为默认拷贝构造函数,属浅拷贝。
CNumber one;
004090EA 8D 4D D4 lea ecx,[one]
004090ED E8 3D AF FF FF call CNumber::CNumber (040402Fh)
004090F2 C7 45 FC 02 00 00 00 mov dword ptr [ebp-4],2
CNumber two(one);
004090F9 8B 45 D4 mov eax,dword ptr [one]
004090FC 89 45 C8 mov dword ptr [two],eax
004090FF C6 45 FC 03 mov byte ptr [ebp-4],3
2.深拷贝
CMyString MyString;
00416273 8D 4D BC lea ecx,[MyString]
00416276 E8 4E DA FE FF call CMyString::CMyString (0403CC9h)
0041627B C6 45 FC 04 mov byte ptr [ebp-4],4
MyString.SetString("Hello");
0041627F 68 1C C0 49 00 push offset string "Hello" (049C01Ch)
00416284 8D 4D BC lea ecx,[MyString]
00416287 E8 37 D1 FE FF call CMyString::SetString (04033C3h)
Show(MyString);
0041628C 51 push ecx
;这里的作用是sub esp,4 主要因为MyString的类型长度为4 push ecx更短更快, 如果长度是其他值
;这里是要变成 sub esp,sizeof(MyString)用来保存参数对象
0041628D 8B CC mov ecx,esp ;保存参数对象的地址
0041628F 89 A5 9C FE FF FF mov dword ptr [ebp-164h],esp ;保存参数对象的地址
00416295 8D 45 BC lea eax,[MyString] ;取对象地址
00416298 50 push eax
00416299 E8 9E CB FE FF call CMyString::CMyString (0402E3Ch) ;调用构造函数
0041629E 89 85 94 FE FF FF mov dword ptr [ebp-16Ch],eax
004162A4 E8 D9 C1 FE FF call Show (0402482h)
004162A9 83 C4 04 add esp,4
CMyString(CMyString& obj){
;栈操作
00408800 55 push ebp
00408801 8B EC mov ebp,esp
00408803 81 EC E4 00 00 00 sub esp,0E4h
00408809 53 push ebx
0040880A 56 push esi
0040880B 57 push edi
0040880C 51 push ecx
0040880D 8D BD 1C FF FF FF lea edi,[ebp-0E4h]
00408813 B9 39 00 00 00 mov ecx,39h
00408818 B8 CC CC CC CC mov eax,0CCCCCCCCh
0040881D F3 AB rep stos dword ptr es:[edi]
;拷贝构造函数主体
0040881F 59 pop ecx
00408820 89 4D F8 mov dword ptr [this],ecx
int nLen = strlen(obj.m_pString);
00408823 8B 45 08 mov eax,dword ptr [obj]
00408826 8B 08 mov ecx,dword ptr [eax]
00408828 51 push ecx
int nLen = strlen(obj.m_pString);
00408829 E8 DD 95 FF FF call _strlen (0401E0Bh)
0040882E 83 C4 04 add esp,4
00408831 89 45 EC mov dword ptr [nLen],eax
this->m_pString = new char[nLen + sizeof(char)];
00408834 8B 45 EC mov eax,dword ptr [nLen]
00408837 83 C0 01 add eax,1
0040883A 50 push eax
0040883B E8 43 AF FF FF call operator new[] (0403783h)
00408840 83 C4 04 add esp,4
00408843 89 85 20 FF FF FF mov dword ptr [ebp-0E0h],eax
00408849 8B 4D F8 mov ecx,dword ptr [this]
0040884C 8B 95 20 FF FF FF mov edx,dword ptr [ebp-0E0h]
00408852 89 11 mov dword ptr [ecx],edx
strcpy(this->m_pString, obj.m_pString);
00408854 8B 45 08 mov eax,dword ptr [obj]
00408857 8B 08 mov ecx,dword ptr [eax]
00408859 51 push ecx
0040885A 8B 55 F8 mov edx,dword ptr [this]
0040885D 8B 02 mov eax,dword ptr [edx]
0040885F 50 push eax
00408860 E8 05 96 FF FF call _strcpy (0401E6Ah)
00408865 83 C4 08 add esp,8
}
00408868 8B 45 F8 mov eax,dword ptr [this] ;返回this指针
0040886B 5F pop edi
0040886C 5E pop esi
0040886D 5B pop ebx
0040886E 81 C4 E4 00 00 00 add esp,0E4h
00408874 3B EC cmp ebp,esp
00408876 E8 F4 9A FF FF call __RTC_CheckEsp (040236Fh)
0040887B 8B E5 mov esp,ebp
0040887D 5D pop ebp
0040887E C2 04 00 ret 4
class CMyString{
public:
CMyString(){
m_pString = NULL;
}
CMyString(CMyString& obj){
// 注:如在拷贝构造中这样拷贝指针,仍然属于浅拷贝,并没有拷贝指针所指向的
// 堆空间中的数据制作副本,仍然会造成错误。
// this->m_pString = obj.m_pString;
int nLen = strlen(obj.m_pString);
this->m_pString = new char[nLen + sizeof(char)];
strcpy(this->m_pString, obj.m_pString);
}
~CMyString(){
if (m_pString != NULL)
{
delete [] m_pString;
m_pString = NULL;
}
}
void SetString(char * pString){
int nLen = strlen(pString);
if (m_pString != NULL)
{
delete [] m_pString;
m_pString = NULL;
}
m_pString = new char[nLen + sizeof(char)];
strcpy(m_pString, pString);
}
char * m_pString;
};