1 #include <iostream> 2 #include <cstring> 3 using namespace std; 4 class ClassTest 5 { 6 public: 7 ClassTest() 8 { 9 c[0] = '\0'; 10 cout << "ClassTest()" << endl; 11 } 12 ClassTest& operator=(const ClassTest &ct) 13 { 14 strcpy(c, ct.c); 15 cout << "ClassTest& operator=(const ClassTest &ct)" << endl; 16 return *this; 17 } 18 ClassTest(ClassTest&& ct) 19 { 20 cout << "ClassTest(ClassTest&& ct)" << endl; 21 } 22 ClassTest & operator=(ClassTest&& ct) 23 { 24 strcpy(c, ct.c); 25 cout << "ClassTest & operator=(ClassTest&& ct)" << endl; 26 return *this; 27 } 28 ClassTest(const char *pc) 29 { 30 strcpy(c, pc); 31 cout << "ClassTest (const char *pc)" << endl; 32 } 33 //private: 34 ClassTest(const ClassTest& ct) 35 { 36 strcpy(c, ct.c); 37 cout << "ClassTest(const ClassTest& ct)" << endl; 38 } 39 virtual int ff() 40 { 41 return 1; 42 } 43 private: 44 char c[256]; 45 }; 46 ClassTest f1() 47 { 48 ClassTest c; 49 return c; 50 } 51 void f2(ClassTest ct) 52 { 53 ; 54 } 55 int main() 56 { 57 ClassTest ct1("ab");//直接初始化 58 ClassTest ct2 = "ab";//複製初始化 59 ClassTest ct3 = ct1;//複製初始化 60 ClassTest ct4(ct1);//直接初始化 61 ClassTest ct5 = ClassTest("ab");//複製初始化 62 ClassTest ct6 = f1(); 63 f1(); 64 f2(ct1); 65 return 0; 66 }
ClassTest ct1("ab");//直接初始化 00B09518 push 0B0DCB8h //"ab"字符串地址 00B0951D lea ecx,[ct1] 00B09523 call ClassTest::ClassTest (0DC101Eh)
ClassTest ct2 = "ab";//複製初始化 00B09528 push 0B0DCB8h //"ab"字符串地址 00B0952D lea ecx,[ct2] 00B09533 call ClassTest::ClassTest (0DC101Eh)
ClassTest ct3 = ct1;//複製初始化 00B09538 lea eax,[ct1] 00B0953E push eax 00B0953F lea ecx,[ct3] 00B09545 call ClassTest::ClassTest (0DC14C4h)
010B3EE0 push ebp 010B3EE1 mov ebp,esp 010B3EE3 sub esp,0CCh 010B3EE9 push ebx 010B3EEA push esi 010B3EEB push edi 010B3EEC push ecx 010B3EED lea edi,[ebp-0CCh] 010B3EF3 mov ecx,33h 010B3EF8 mov eax,0CCCCCCCCh 010B3EFD rep stos dword ptr es:[edi] 010B3EFF pop ecx 010B3F00 mov dword ptr [this],ecx 010B3F03 mov eax,dword ptr [this] //eax指向ct3對象地址 010B3F06 mov dword ptr [eax],10BDC70h //虛表指針存儲在對象偏移量爲0的地方 010B3F0C mov esi,dword ptr [__that] //esi存儲ct1對象地址 010B3F0F add esi,4 //將esi加4,跳過4個字節的虛表指針,指向ct1後面的成員變量c 010B3F12 mov edi,dword ptr [this] 010B3F15 add edi,4 //edi指向ct2後面成員變量c 010B3F18 mov ecx,40h 010B3F1D rep movs dword ptr es:[edi],dword ptr [esi] //將ct1中字符數組元素拷貝到ct3字符數組 010B3F1F mov eax,dword ptr [this] //經過eax返回ct3對象地址 010B3F22 pop edi 010B3F23 pop esi 010B3F24 pop ebx 010B3F25 mov esp,ebp 010B3F27 pop ebp
ClassTest ct4(ct1);//直接初始化 010B954A lea eax,[ct1] 010B9550 push eax 010B9551 lea ecx,[ct4] 010B9557 call ClassTest::ClassTest (0DC14C4h)
ClassTest ct5 = ClassTest();//複製初始化 010B955C lea ecx,[ct5] 010B9562 call ClassTest::ClassTest (0DC12ADh)
ClassTest() 010B4C70 push ebp 010B4C71 mov ebp,esp 010B4C73 sub esp,0CCh 010B4C79 push ebx 010B4C7A push esi 010B4C7B push edi 010B4C7C push ecx 010B4C7D lea edi,[ebp-0CCh] 010B4C83 mov ecx,33h 010B4C88 mov eax,0CCCCCCCCh 010B4C8D rep stos dword ptr es:[edi] 010B4C8F pop ecx 010B4C90 mov dword ptr [this],ecx 010B4C93 mov eax,dword ptr [this] 010B4C96 mov dword ptr [eax],10BDC70h { c[0] = '\0'; 010B4C9C mov eax,1 010B4CA1 imul ecx,eax,0 010B4CA4 mov edx,dword ptr [this] 010B4CA7 mov byte ptr [edx+ecx+4],0 cout << "ClassTest()" << endl;
ClassTest ct6 = f1(); 010B9567 lea eax,[ct6] 010B956D push eax 010B956E call f1 (0DC14BFh) 010B9573 add esp,4
ClassTest f1() { 00DC5830 push ebp //棧幀開始 00DC5831 mov ebp,esp 00DC5833 sub esp,1D0h 00DC5839 push ebx 00DC583A push esi 00DC583B push edi 00DC583C lea edi,[ebp-1D0h] 00DC5842 mov ecx,74h 00DC5847 mov eax,0CCCCCCCCh 00DC584C rep stos dword ptr es:[edi] 00DC584E mov eax,dword ptr ds:[00DD0000h] //初始化棧 00DC5853 xor eax,ebp 00DC5855 mov dword ptr [ebp-4],eax ClassTest c; 00DC5858 lea ecx,[c] //c的值ebp+FFFFFEF4h即ebp-12,說明c是一個棧內局部變量 00DC585E call ClassTest::ClassTest (0DC12ADh) //調用默認構造函數初始化c return c; 00DC5863 lea eax,[c] 00DC5869 push eax //c對象地址 00DC586A mov ecx,dword ptr [ebp+8] //ct6對象地址 00DC586D call ClassTest::ClassTest (0DC14BAh) //調用移動構造函數,初始化ct6 00DC5872 mov eax,dword ptr [ebp+8] //返回ct6對象地址 } 00DC5875 push edx 00DC5876 mov ecx,ebp 00DC5878 push eax 00DC5879 lea edx,ds:[0DC58A4h] 00DC587F call @_RTC_CheckStackVars@8 (0DC1136h) 00DC5884 pop eax //省略餘下代碼
f1(); 00DC9576 lea eax,[ebp-814h] 00DC957C push eax 00DC957D call f1 (0DC14BFh) 00DC9582 add esp,4
f2(ct1); 010F9392 sub esp,104h //開闢棧空間,生成一個臨時對象,恰好是260個字節(256+4,即虛表指針和私有的char型數組的總大小) 010F9398 mov ecx,esp //將esp棧頂指針做爲臨時對象的起始地址 010F939A lea eax,[ct1] //傳入ct1對象地址 010F93A0 push eax 010F93A1 call ClassTest::ClassTest (010F1078h) 010F93A6 call f2 (010F14BFh) 010F93AB add esp,104h
1 ClassTest ct2 ="ab"; //至關於ClassTest ct2("ab"); 2 ClassTest ct5 =ClassTest("ab"); //至關於ClassTest ct5("ab")
1 f1(); //臨時對象用於存儲f1的返回值 2 f2(ct1); //臨時對象用於拷貝實參,並傳入函數
1 ClassTest ct6 = f1();
ClassTest ct2 = "ab";//複製初始化
ClassTest ct2("ab");//直接初始化
本文連接:【原創】c++拷貝初始化和直接初始化的底層區別 http://www.cnblogs.com/cposture/p/4925736.htmlhtml