用彙編的眼光看C (之遞迴函式與模板類) 19

2022-03-24 15:23:52 字數 2492 閱讀 4894

遞迴,相信有過基本c語言經驗的朋友都明白,就是函式自己呼叫自己。所以,本質上說,它和普通的函式呼叫沒有什麼區別。今天之所以會把模板類和遞迴聯絡在一起,是因為我們可以用遞迴的方法實現模板的遞迴。閒話不多說,我們先從乙個統計函式開始說起。

[cpp]view plain

copy

intprocess(

intm)  

return

count;  

}[cpp]view plain

copy

intprocess(

intm)  

我們看到,遞迴的目的就是把大的計算拆分到小的計算,最後再進行計算合併。比如說,我們計算process(5),那就需要計算 process(4);process(4)又需要計算process(3);process(3)又需要計算 process(2);process(2)有需要計算process(1);process(1)計算有需要 process(0);process(0)就可以得到結果了,數值為0,那麼進而可以得到process(1),以此類推,最後可以得到結果 process(5)的數值。這就是遞迴處理的全過程。

那麼,這和模板類有什麼關係,我們可以看看下面這個範例:

[cpp]view plain

copy

template

<

intm>  

class

calculate  

};  

template

<>  

class

calculate<0>  

};  

上面這段**非常有意思。我們發現模板的資料型別不再是int、double或者是自己定義的資料型別,而是乙個乙個具體的數字。但是每一種數字也代表 了一種型別,所以說,calculate<5>和calculate<4>就是兩種不同的類。除此之外,我們還是用到了靜態處理 函式。但是這裡的靜態函式有點特別,我們發現靜態函式process需要呼叫另外乙個類的靜態函式,也就是calculate的靜 態函式才能獲得結果。所以為了獲得結果,我們需要建立很多的類和很多的靜態函式。那麼,類什麼時候結束呢?我們看到了calculate下面還有乙個類, 那就是calculate的特化模板,也就是說那m=0的時候,並不再繼續向下處理了,計算開始回歸。那麼這個類怎麼應用呢,我們來一起看一看:

[cpp]view plain

copy

258:      

intvalue = calculate<5>::process();  

004013d8   call        @ilt+45(calculate<5>::process) (00401032)  

004013dd   mov         dword ptr [ebp-4],eax  

259:      return

;  260:  }  

上面就是呼叫引申的彙編的**。彙編和一般的函式呼叫無異,我們可以跟進去看看:

[cpp]view plain

copy

242:          

return

calculate::process() + m;  

00401f68   call        @ilt+40(calculate<4>::process) (0040102d)  

00401f6d   add         eax,5  

243:      }  

上面的**省略了中間的跳轉。我們發現**繼續呼叫了calculate<4>的靜態處理函式。這種呼叫當然會一直持續下去。那什麼時候結 束呢?對。就是前面說過的calculate<1>的靜態函式,就是前面說的特化函式,我們可以一起看看:

[cpp]view plain

copy

250:      

static

intprocess()  

251:        

004020aa   pop         edi  

004020ab   pop         esi  

004020ac   pop         ebx  

004020ad   mov         esp,ebp  

004020af   pop         ebp  

004020b0   ret  

看的出來,這裡才是真正的遞迴出口,到了這裡之後,函式開始折返,這也就意外著我們的計算即將結束。所有的流程和遞迴非常相似。所以遞迴函式和模板遞迴的區別就是一點:遞迴函式是在**執行的時候完成的,模板遞迴是在編譯的時候完成的。

思考題:

自己編寫乙個階乘的函式?嘗試一下是否可以轉變成遞迴函式?是否可以用模板類遞迴得到呢?

【預告: 下面一片部落格介紹泛型函式處理】

用彙編的眼光看C (之特殊函式)

這裡說的函式主要指的是inline函式 static函式。inline函式比較特殊,它既具有巨集的性質,同時也能讓編譯器對它進行函式檢查。static函式同樣也比較特殊,它只可以被同檔案的函式使用。如果static函式在include檔案中,那麼這個標頭檔案只要被使用一次,那麼這個函式就要在exec...

用彙編的眼光看c (之模板函式)

如果說模板類定義的是一種資料型別,那麼模板函式定義的就是一種函式。既然是函式,那麼就有輸入資料和輸出資料。和模板類的概念差不多,模板函式的初衷也是為了在函式操作上抽取共同的特性,遮蔽的是型別的不同和差異。我們可以通過下面乙個簡單的 說明問題 view plain intint compare int...

用彙編的眼光看c (之模板函式)

如果說模板類定義的是一種資料型別,那麼模板函式定義的就是一種函式。既然是函式,那麼就有輸入資料和輸出資料。和模板類的概念差不多,模板函式的初衷也是為了在函式操作上抽取共同的特性,遮蔽的是型別的不同和差異。我們可以通過下面乙個簡單的 說明問題 int int compare int a,int b d...