生活随笔
收集整理的這篇文章主要介紹了
用汇编的眼光看C++(之拷贝、赋值函数)
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
拷貝構(gòu)造函數(shù)和復(fù)制函數(shù)是類里面比較重要的兩個(gè)函數(shù)。兩者有什么區(qū)別呢?其實(shí)也很簡(jiǎn)單,我們可以舉個(gè)例子,加入有這樣一個(gè)類的定義:
[cpp]?view plaincopy
class?apple?? {?? public:?? ????apple()?{??printf("apple()!\n");}?? ????apple(apple&?a)?{??printf("copy?apple()!\n");}?? ????apple&?operator=(apple&?a)?{??printf("=?apple()\n");?return?*this;}?? ????~apple()?{??printf("~apple()!\n");}?? ????void?print()?const?{??return;}?? };??
?? ?那么我們?cè)谌缦碌暮瘮?shù)里面進(jìn)行調(diào)用的時(shí)候,調(diào)用的函數(shù)分別是哪些呢?
[cpp]?view plaincopy
void?process()?? {?? ????apple?a,?c;?? ????apple?b?=a;?? ????c?=?b;?? }?? ?? ?其實(shí)匯編的結(jié)果是這樣的,大家可以一起看一下,自己嘗試讀一下。如果一次不是很明白,可以多讀幾次。
[cpp]?view plaincopy
70:???????apple?a,?c;?? 0040127D???lea?????????ecx,[ebp-10h]?? 00401280???call????????@ILT+70(apple::apple)?(0040104b)?? 00401285???mov?????????dword?ptr?[ebp-4],0?? 0040128C???lea?????????ecx,[ebp-14h]?? 0040128F???call????????@ILT+70(apple::apple)?(0040104b)?? 00401294???mov?????????byte?ptr?[ebp-4],1?? 71:???????apple?b?=a;?? 00401298???lea?????????eax,[ebp-10h]?? 0040129B???push????????eax?? 0040129C???lea?????????ecx,[ebp-18h]?? 0040129F???call????????@ILT+50(apple::apple)?(00401037)?? 004012A4???mov?????????byte?ptr?[ebp-4],2?? 72:???????c?=?b;?? 004012A8???lea?????????ecx,[ebp-18h]?? 004012AB???push????????ecx?? 004012AC???lea?????????ecx,[ebp-14h]?? 004012AF???call????????@ILT+75(apple::operator=)?(00401050)?? 73:???}?? 004012B4???mov?????????byte?ptr?[ebp-4],1?? 004012B8???lea?????????ecx,[ebp-18h]?? 004012BB???call????????@ILT+0(apple::~apple)?(00401005)?? 004012C0???mov?????????byte?ptr?[ebp-4],0?? 004012C4???lea?????????ecx,[ebp-14h]?? 004012C7???call????????@ILT+0(apple::~apple)?(00401005)?? 004012CC???mov?????????dword?ptr?[ebp-4],0FFFFFFFFh?? 004012D3???lea?????????ecx,[ebp-10h]?? 004012D6???call????????@ILT+0(apple::~apple)?(00401005)?? 004012DB???mov?????????ecx,dword?ptr?[ebp-0Ch]?? 004012DE???mov?????????dword?ptr?fs:[0],ecx?? 004012E5???pop?????????edi?? 004012E6???pop?????????esi?? 004012E7???pop?????????ebx?? 004012E8???add?????????esp,58h?? 004012EB???cmp?????????ebp,esp?? 004012ED???call????????__chkesp?(004087c0)?? 004012F2???mov?????????esp,ebp?? 004012F4???pop?????????ebp?? 004012F5???ret?? ?? ?代碼有點(diǎn)長(zhǎng),大家可以一句一句來(lái)看,比如說(shuō)就按照70、71、72、73分別查看對(duì)應(yīng)的匯編代碼:
?? ?(1)70句: 我們看到函數(shù)做了兩次函數(shù)調(diào)用,恰好就是apple的構(gòu)造函數(shù)調(diào)用。這也正好對(duì)應(yīng)著兩個(gè)臨時(shí)變量a和c,兩個(gè)變量的地址分別是【ebp-10】和【ebp-14】,這里也可以看出整個(gè)類的大小就是4個(gè)字節(jié),就是一塊存放數(shù)據(jù)的普通內(nèi)存。而構(gòu)造函數(shù)之所以能和對(duì)應(yīng)的內(nèi)存綁定在一起,主要是因?yàn)閑cx記錄了內(nèi)存的起始地址,這在C++編譯中是十分關(guān)鍵的。我們看到的C++構(gòu)造函數(shù)好像是沒(méi)有綁定內(nèi)存,實(shí)際上在VC里面已經(jīng)做好了約定,ecx就是this指針,就是類的內(nèi)存起始地址。有興趣的同學(xué)看看G++編譯的時(shí)候,采用的this指針是哪個(gè)寄存器保存的?(其實(shí)是eax)
?? ?(2)71句:通過(guò)對(duì)應(yīng)看到了eax記錄了引用變量的地址,而ecx是ebp下面緊挨著四個(gè)字節(jié)。但是函數(shù)調(diào)用的地址和前面的缺省構(gòu)造函數(shù)不太一樣,所以我們大膽猜測(cè),這里的構(gòu)造函數(shù)這是拷貝構(gòu)造函數(shù),我們可以在調(diào)試的時(shí)候查看一下打印消息。
?? ?(3)72句:0x4012AF語(yǔ)句已經(jīng)清楚地告訴了我們,這里調(diào)用的函數(shù)就是operator=函數(shù),這一部分是算術(shù)符重載的內(nèi)容,我們?cè)诤竺娴牟┛蜁?huì)重點(diǎn)介紹。
?? ?(4)73句: 前面我們講過(guò),析構(gòu)函數(shù)在函數(shù)調(diào)用結(jié)束的時(shí)候被被自動(dòng)調(diào)用,那么這里我們看到卻是出現(xiàn)了三個(gè)調(diào)用?這三個(gè)變量正好是我們之前說(shuō)的a、b、c三個(gè)變量。那么這三個(gè)變量調(diào)用的次序是怎樣的呢?我們可以查看一下變量的地址,分別是【ebp-18h】、【ebp-14h】、【ebp-10h】,這正好和變量出現(xiàn)的順序相反。所以我們看到,析構(gòu)函數(shù)和構(gòu)造函數(shù)是嚴(yán)格一一對(duì)應(yīng)的,誰(shuí)先出現(xiàn),誰(shuí)后析構(gòu)。
【預(yù)告: 下面的博客我們會(huì)對(duì)構(gòu)造、析構(gòu)中出現(xiàn)的一些現(xiàn)象進(jìn)行總結(jié)】
總結(jié)
以上是生活随笔為你收集整理的用汇编的眼光看C++(之拷贝、赋值函数)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。