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

2021-05-28 07:54:00 字數 4260 閱讀 3537

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

int int_compare(int a, int b)

double double_compare(double a, double b)

上面的一段**是取較大值的一段**。兩個函式之間最大的差別就是輸入資料型別和輸出資料型別之間的差別,那我們有沒有一種辦法可以遮蔽這種資料型別之間的差別呢?有。那就是函式模板:

template type compare(type a, type b)

可以看到,模板函式和普通函式沒有什麼區別,只是在函式的上面把型別抽象成了type,那麼模板函式應該怎麼使用呢?

246:      int i_value = compare(2, 3);

00401458 push 3

0040145a push 2

0040145c call @ilt+10(compare) (0040100f)

00401461 add esp,8

00401464 mov dword ptr [ebp-4],eax

247: double d_value = compare(2.3, 3.1);

00401467 push 4008cccch

0040146c push 0cccccccdh

00401471 push 40026666h

00401476 push 66666666h

0040147b call @ilt+5(compare) (0040100a)

00401480 add esp,10h

00401483 fstp qword ptr [ebp-0ch]

248: }

彙編**表明,兩個compare呼叫的函式位址並不是一致的。其中整數的compare位址是0x40100f,而double的位址是0x0040100a。這說明編譯器在編譯的時候幫我們同時生成了兩個compare函式。所以說,模板類的本質就是在編譯器增加判斷處理工作的同時,減少手工的重複勞動。同時和模板類不一樣,模板函式不需要顯示定義函式的引數型別,這是因為可以從入參判斷出函式的型別。

如果引數型別是 class型別呢? 我們可以試一試。首先定義基本class:

class data

~data() {}

int get_value()

int operator > (data& d)

};

接著,我們呼叫compare函式:

256:      data m(4), n(2);

0040148d push 4

0040148f lea ecx,[ebp-10h]

00401492 call @ilt+40(data::data) (0040102d)

00401497 mov dword ptr [ebp-4],0

0040149e push 2

004014a0 lea ecx,[ebp-14h]

004014a3 call @ilt+40(data::data) (0040102d)

004014a8 mov byte ptr [ebp-4],1

257: data p = compare(m,n);

004014ac mov eax,dword ptr [ebp-14h]

004014af push eax

004014b0 mov ecx,dword ptr [ebp-10h]

004014b3 push ecx

004014b4 lea edx,[ebp-18h]

004014b7 push edx

004014b8 call @ilt+15(compare) (00401014)

004014bd add esp,0ch

258: }

256行: data構造了兩個基本變數m和n

為了看到算術符》過載,我們跟進compare函式:

241:      return a > b ? a : b;

0040212b lea eax,[ebp+10h]

0040212e push eax

0040212f lea ecx,[ebp+0ch]

00402132 call @ilt+55(data::operator>) (0040103c)

00402137 test eax,eax

00402139 je compare+53h (00402143)

0040213b lea ecx,[ebp+0ch]

0040213e mov dword ptr [ebp-18h],ecx

00402141 jmp compare+59h (00402149)

00402143 lea edx,[ebp+10h]

00402146 mov dword ptr [ebp-18h],edx

00402149 mov eax,dword ptr [ebp-18h]

0040214c mov dword ptr [ebp-10h],eax

0040214f mov ecx,dword ptr [ebp-10h]

00402152 mov edx,dword ptr [ecx]

00402154 mov eax,dword ptr [ebp+8]

00402157 mov dword ptr [eax],edx

00402159 mov ecx,dword ptr [ebp-14h]

0040215c or ecx,1

0040215f mov dword ptr [ebp-14h],ecx

00402162 mov byte ptr [ebp-4],1

00402166 lea ecx,[ebp+0ch]

00402169 call @ilt+25(data::~data) (0040101e)

0040216e mov byte ptr [ebp-4],0

00402172 lea ecx,[ebp+10h]

00402175 call @ilt+25(data::~data) (0040101e)

0040217a mov eax,dword ptr [ebp+8]

我們發現compare模板語句下面構建了很多彙編語句,有一些冗長,我們可以大略介紹一下:

(1)  開頭呼叫call 0x0040103c函式就是呼叫過載運算子函式,[ebp-18h]表示即將被複製的是a資料還是b資料

(2) 比較返回結果後,開始複製資料,具體見0x402157,其中臨時變數[ebp-14h]和臨時變數[ebp-4]的操作可以忽略

(3) 函式返回前,對臨時變數a和b進行析構處理,見**0x402169和**0x402175。

注意:

(1)編寫模板函式前先保證自己的函式是編寫正確的

(2)模板函式的優先順序低於非模板函式

(3)模板函式的型別可以是自定義型別,也可以是c、c++語言的基本型別

(4)模板函式的使用經常和類的算術運算子混合使用,注意技巧

(5)模板函式中涉及指標部分的內容,務必注意

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

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

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

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

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

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