前段時(shí)間讀了一本書(shū)《C++沉思錄》,偶有感,摘錄如下:
模板和泛型算法(摘自 《c++沉思錄》):
一個(gè)特例:
1.假設(shè)我們希望從整數(shù)數(shù)組中找到第一個(gè)等于某給定值的元素.編寫(xiě)如下代碼:
const int*
find1(const int* array, int n, int x)
{
const int *p = array;
for( int i = 0; i < n; i++)
{
if(*p==x)
return p;
++p;
}
return 0;
}
2.泛型化元素類(lèi)型:
用類(lèi)型T來(lái)表示整型等,適當(dāng)?shù)臅r(shí)候可以把const也包含在T中,得到如下函數(shù).
template<class T>
T* find2(T* array, int n, constT& x)
{
T* p = array;
for(int i=0; i<n; i++)
{
if(*p==x)
return p;
++p;
}
return 0;
}
3.推遲計(jì)數(shù).
為了避免預(yù)先知道有多少個(gè)元素,我們改變函數(shù),使它接受指向第一個(gè)元素和最后一個(gè)元素之后元素的指針.
template<class T>
T* find3(T* array, T* beyond, constT& x)
{
T* p = array;
while(p!=beyond)
{
if(*p ==x)
return x;
++p;
}
return 0;
}
用!=而不用<來(lái)判斷循環(huán)結(jié)束并不是偶然.從某種角度來(lái)說(shuō),兩者沒(méi)有區(qū)別,如果find3的輸入有意義,則p就小于beyond,直到它們相等為止.但是,由<加以總體排序的類(lèi)型通常也能用!=來(lái)進(jìn)行比較.另一方面,考慮一下我們以后可能會(huì)用到來(lái)代替指針的類(lèi)型,他們可以很好地定義!=,但不一定能定義<.此時(shí),使用<就是一個(gè)不合理的假設(shè).
另外,我們還假設(shè)了,0可以轉(zhuǎn)換成一個(gè)與其他所有的值不同的指針值.我們稍微做一點(diǎn)改變,以避免這種假設(shè):如果程序中要找的值沒(méi)找到,它就返回beyond而不是0.
template<class T>
T* find4(T* array, T* beyond, constT& x)
{
T* p = array;
while(p!=beyond)
{
if(*p ==x)
return x;
++p;
}
return beyond;
}
因?yàn)槌绦蛞捶祷剡m當(dāng)?shù)腡*, 要么返回beyond.故程序代碼可以被修改如下:
template<class T>
T* find5(T* array, T* beyond, constT& x)
{
T* p = array;
while(p!=beyond && *p != x)
++p;
return p;
}
4.地址的獨(dú)立性
到目前為止,我們還是依賴(lài)于傳遞來(lái)的指針,該指針要指向要查找的數(shù)據(jù)的開(kāi)頭.但是如果仔細(xì)分析一下,會(huì)發(fā)現(xiàn)我們只依賴(lài)于指針的某些保留特性:
1)可以把指針當(dāng)參數(shù)接收,并把它們作為結(jié)果返回.
2)可以比較指針是否相等.
3)可以解除引用,以便得到值:*p.
4)可以遞增,以指向下一個(gè)元素.
只要符合上述條件的類(lèi)型即可,不一定是指針類(lèi)型.假設(shè)把T*作為模板參數(shù),我們就取消了對(duì)指針的依賴(lài):
template<class P,class T>
T* find6(P start, p beyond, constT& x)
{
while(start !=beyond && *start != x)
++start;
return start;
}
我們已經(jīng)完全剔除了函數(shù)中關(guān)于具體類(lèi)型的信息.根本沒(méi)有要求p是指針,只要求p滿足上述的四個(gè)特性.