一、模板
對于一個交換函數(shù),雖然c++支持函數(shù)重載,我們可以對多個交換函數(shù)起相同的名字:
1
2
3
4
5
6
7
8
9
10
11
12
|
void swap( int & left, int & right) { int temp = left; left = right; right = temp; } void swap( double & left, double & right) { double temp = left; left = right; right = temp; } |
但是依然有不足的地方,比如如果我們要交換其他類型,比如char或者類類型,那還是得再寫一個交換函數(shù),這樣原來寫好的其他類型的交換函數(shù)就沒有復(fù)用起來,大大降低了效率。
因此,c++引入了模板的概念,通過模板,即可實(shí)現(xiàn)一份代碼交換不同數(shù)據(jù)。
模板,其實(shí)就是告訴編譯器一個模子,讓編譯器根據(jù)不同的類型利用該模子來生成代碼。
1.1.函數(shù)模板
**泛型編程:**在之前,函數(shù)都是針對某個具體的類型(比如int,char),而泛型則是針對一個廣泛的類型。模板則是泛型編程的基礎(chǔ)。
所以函數(shù)模板的參數(shù)并不是一個具體的類型,只有當(dāng)調(diào)用時才能確定具體的類型。
其語法為:
1
2
3
4
5
|
//定義模板參數(shù)t可以用typename,也可以使用class template < typename t1, typename t2,......, typename tn> 返回值類型 函數(shù)名(用泛型指定的參數(shù)列表) { } |
以交換函數(shù)為例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
template < typename t> void swap(t& left, t& right) { t temp = left; left = right; right = temp; } int main() { int a = 10, b = 20; double c = 1.1, d = 2.2; swap(a, b); swap(c, d); cout << a << " " << b << endl; cout << c << " " << d << endl; } |
從反匯編可以看出,這兩個函數(shù)調(diào)用的并不是同一個函數(shù):
這是因?yàn)楹瘮?shù)模板不是一個實(shí)際的函數(shù),編譯器不會為其生成可執(zhí)行代碼。當(dāng)調(diào)用函數(shù)模板時,編譯器會對函數(shù)模板進(jìn)行推演,根據(jù)傳入實(shí)參的類型推出t的類型,然后實(shí)例化出不同類型的函數(shù)。
1.1.1.兩種函數(shù)模板的實(shí)例化
用不同類型的參數(shù)使用函數(shù)模板時,稱為函數(shù)模板的實(shí)例化。
1.隱式實(shí)例化
讓編譯器根據(jù)實(shí)參推演模板參數(shù)的實(shí)際類型
當(dāng)有多個類型的實(shí)參而模板參數(shù)列表中只有一個t時,編譯器將無法推演出t的類型,此時可以將實(shí)參進(jìn)行類型強(qiáng)轉(zhuǎn):
有趣的是,強(qiáng)轉(zhuǎn)后需要用const t來接收,因?yàn)閺?qiáng)轉(zhuǎn)后傳入的并不是c,而是c的臨時變量,這個臨時變量是具有常屬性的。
2.顯式實(shí)例化
在函數(shù)名后的<>中指定模板參數(shù)的實(shí)際類型
通過這種方式可以不讓編譯器推演類型,而是使用我們指定的類型。
當(dāng)然對于類型不同的參數(shù)也要使用const t來接收。
1.1.2.模板參數(shù)的匹配原則
一個非模板函數(shù)可以和一個同名的函數(shù)模板同時存在,調(diào)用的時候如果與非模板函數(shù)匹配,編譯器會優(yōu)先調(diào)用非模板函數(shù)。如果非模板函數(shù)不匹配或者進(jìn)行了實(shí)例化,則會調(diào)用函數(shù)模板。
1.2.類模板
對于一個類的成員變量也可以使用模板,這樣在定義類對象的時候就可以實(shí)例化出具有不同類型的成員變量和成員函數(shù)的對象了。
如果類模板中函數(shù)放在類外進(jìn)行定義時,需要加模板參數(shù)列表,否則會找不到t。
模板也不支持分離編譯,建議定義在一個文件中。
以動態(tài)順序表為例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
template < class t> class vector { public : vector( size_t capacity = 10) : _pdata( new t[capacity]) , _size(0) , _capacity(capacity) {} ~vector(); //頭插尾插等函數(shù)實(shí)現(xiàn)。。。 size_t size() { return _size; } t& operator[]( size_t pos) { assert (pos < _size); return _pdata[pos]; } private : t* _pdata; size_t _size; size_t _capacity; }; //類模板中函數(shù)放在類外進(jìn)行定義時,需要加模板參數(shù)列表,否則會 template < class t> vector<t>::~vector() { if (_pdata) delete [] _pdata; _size = _capacity = 0; } int main() { vector< int > s1; vector< double > s2; //實(shí)例化兩個不同的類對象 return 0; } |
類模板實(shí)例化與函數(shù)模板實(shí)例化不同,類模板實(shí)例化只能顯示實(shí)例化,需要在類模板名字后跟<>,然后將實(shí)例化的類型放在<>中即可,類模板名字不是真正的類,而實(shí)例化的結(jié)果才是真正的類。
二、stl
stl,英文全稱 standard template library,中文可譯為標(biāo)準(zhǔn)模板庫或者泛型庫,其包含有大量的模板類和模板函數(shù),是 c++ 提供的一個基礎(chǔ)模板的集合,用于完成諸如輸入/輸出、數(shù)學(xué)計算等功能。
stl有六大組件,但主要包含容器、算法和迭代器三個部分。
容器(containers):用來管理某類對象的集合。各種數(shù)據(jù)結(jié)構(gòu),如vector、list、deque、set、map等,用來存放數(shù)據(jù),從實(shí)現(xiàn)角度來看,stl容器是一種class template。
算法(algorithms):用來處理對象集合中的元素,各種常用的算法,如sort、find、copy、for_each。從實(shí)現(xiàn)的角度來看,stl算法是一種function template。
迭代器(iterators):用來在一個對象集合的元素上進(jìn)行遍歷動作。扮演了容器與算法之間的膠合劑,共有五種類型,從實(shí)現(xiàn)角度來看,迭代器是一種將operator* , operator-> , operator++, operator–等指針相關(guān)操作予以重載的class template。所有stl容器都附帶有自己專屬的迭代器,只有容器的設(shè)計者才知道如何遍歷自己的元素。原生指針(native pointer)也是一種迭代器。
仿函數(shù):行為類似函數(shù),可作為算法的某種策略。從實(shí)現(xiàn)角度來看,仿函數(shù)是一種重載了operator()的class 或者class template。
適配器:一種用來修飾容器或者仿函數(shù)或迭代器接口的東西。
空間配置器:負(fù)責(zé)空間的配置與管理。從實(shí)現(xiàn)角度看,配置器是一個實(shí)現(xiàn)了動態(tài)空間配置、空間管理、空間釋放的class tempalte。
stl存在以下缺陷:
stl庫的更新太慢了。上一版靠譜是c++98,中間的c++03基本一些修訂。c++11出來已經(jīng)相隔了13年,stl才進(jìn)一步更新。stl現(xiàn)在都沒有支持線程安全。并發(fā)環(huán)境下需要我們自己加鎖。且鎖的粒度是比較大的。stl極度的追求效率,導(dǎo)致內(nèi)部比較復(fù)雜。比如類型萃取,迭代器萃取。stl的使用會有代碼膨脹的問題,比如使用vector/vector/vector這樣會生成多份代碼,當(dāng)然這是模板語法本身導(dǎo)致的。
總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注服務(wù)器之家的更多內(nèi)容!
原文鏈接:https://blog.csdn.net/qq_52670477/article/details/120398880