1.C++模板簡(jiǎn)介
1.模板概觀
模板是c++的一種特性,允許函數(shù)或類(對(duì)象)通過泛型的形式表現(xiàn)或運(yùn)行
c++通常使用兩種模板
a.類模板估蹄,使用泛型參數(shù)的類
b.函數(shù)模板,使用泛型參數(shù)的函數(shù)
2.函數(shù)模板
template<typename T>
inline T Max(T a,T b)
{
return (a > b)?a:b;
}
從語法上講,class和typename沒有區(qū)別操禀,但不能使用struct勇边; 盡量使用typename犹撒; 模板實(shí)例化,編譯器自動(dòng)的粒褒; 如果該型別不支持函數(shù)所使用的操作识颊,會(huì)報(bào)錯(cuò); (比如std::complex沒有重載>奕坟,但函數(shù)里使用了complex類的>) 模板會(huì)被編譯兩次祥款,一次是本身,一次是調(diào)用時(shí)候的實(shí)例化执赡; 參數(shù)推導(dǎo)镰踏,每個(gè)T必須嚴(yán)格匹配,不允許自動(dòng)類型轉(zhuǎn)換沙合; 比如Max(1,2.0); 解決1:用static_cast或強(qiáng)制轉(zhuǎn)換:Max(static_cast(1),2.0) 解決2:顯式指定T的類型:Max(1,2.0)//1可以轉(zhuǎn)換成double 函數(shù)模板可以像普通函數(shù)一樣重載奠伪,可以重載同名的非模板函數(shù); Max('a',4.2)參數(shù)類型不同首懈,當(dāng)存在非模板函數(shù)時(shí)绊率,會(huì)調(diào)用非模板函數(shù)進(jìn)行類型轉(zhuǎn)換; 重載版本的聲明必須位于調(diào)用位置之前究履;
3.類模板
類也可以通過參數(shù)泛化滤否,從而可以創(chuàng)建出一族不同類型的類實(shí)例(對(duì)象);
類模板實(shí)參可以使某一型別或者常量(僅限int或enum)最仑;
在內(nèi)部T像其他類型一樣定員成員變量和成員函數(shù)藐俺;
如果類模板中需要使用到這個(gè)類模板本身炊甲,應(yīng)該使用其完整定義,帶<...>的形式欲芹;
Stack >兩個(gè)尖括號(hào)不要連到一起卿啡,會(huì)編譯成<<,經(jīng)過驗(yàn)證菱父,新版編譯器不會(huì)出現(xiàn)該問題;
類模板特化颈娜,要把所有成員函數(shù)都重寫一遍;可以添加新的成員函數(shù)浙宜;
偏特化:
template <typename T1,typename T2>class MyClass{...};
template <typename T> class MyClass{...}; 偏特化成同類型;
template <typename T>class MyClass<T,int>{...}; 偏特化成非泛型;
template <typename T1,typename T2>class MyClass<T1*,T2*>{...}; 偏特化成指針;
如果調(diào)用同等的匹配不止一個(gè)偏特化官辽,二義性,編譯器不會(huì)通過粟瞬;
如下所示:
MyClass<int,int>; //可同時(shí)匹配2同仆,3同類型和參數(shù)2偏特化為int
MyClass<int*,int*>; //可同時(shí)匹配2,4同類型和指針
類模板參數(shù)可以有默認(rèn)值亩钟,如下:
template<typename T,typename TContainer = std::vector<T>>
class stack
{
private:TContainer m_Container;
}
2.泛型編程
1.概觀
泛型編程是一種編程方法乓梨,這種方法將型別(type)以一種to-be-specified-later的方式給出,等到需要調(diào)用時(shí)清酥,再以參數(shù)方式扶镀,通過具體的、特定的型別實(shí)例化一個(gè)具體的方法或?qū)ο?泛型編程是一種編程想法或思維焰轻,并不依賴于具體語言
2.特性 Traits
A[0],A[1],A[2].....A[n]
如何構(gòu)建型別為T的初始類型臭觉,姑且使用T(0);
如果求和函數(shù),求出的結(jié)果超出了類型的容量辱志,
比如char數(shù)組”abc“蝠筑,求和的值大于char類型容量255
會(huì)溢出overflow,此時(shí)可以強(qiáng)制使用來儲(chǔ)存揩懒,或者使用Traits什乙; Sigma函數(shù)的返回值的型別叫做T的trait;
T -> association -> characteristic of T -> another type -> trait;
Traits可以實(shí)現(xiàn)為模板類已球,而關(guān)聯(lián)(association)是針對(duì)每個(gè)具體型別T的特化臣镣;
在這個(gè)例子里traits命名為Sigma Traits,叫做traits模板(traits template);
Traits可以實(shí)現(xiàn)為模板類;
template class SigmaTraits{};
template<>class SigmaTraits{
public: typedef int Return Type;} //當(dāng)傳進(jìn)去的是char,return的類型變成int智亮;
把每個(gè)傳入類型都指定return的類型忆某;
typename SigmaTrais::ReturnType //這一串是返回類型的寫法;
3.迭代器
本身是一個(gè)對(duì)象,指向另一個(gè)(可以被迭代的)對(duì)象阔蛉;
算法通常以迭代器作為輸入?yún)?shù)弃舒;
3.容器
1.Vector
存放任意型別的動(dòng)態(tài)數(shù)組;數(shù)據(jù)結(jié)構(gòu)和操作與數(shù)組類似状原,在內(nèi)存中是一段地址連續(xù)的空間聋呢;
Vector支持動(dòng)態(tài)空間大小調(diào)整苗踪,隨著元素的加入,vector內(nèi)部會(huì)自動(dòng)擴(kuò)充內(nèi)存空間坝冕;
頭文件vector徒探,名稱空間std;
2.創(chuàng)建
創(chuàng)建一個(gè)T型別的空vector: vectorv;
創(chuàng)建一個(gè)容量是n的T型別vector: vectorv(n);
創(chuàng)建一個(gè)容量是n的T型別vector喂窟,并且都初始化為i: vectorv(n,i);
創(chuàng)建一個(gè)已有v的拷貝: vectorcopyOfV(v);
通過一個(gè)數(shù)組創(chuàng)建一個(gè)vector: int array[]={1,2,3,4,5,6,7};
vectorv(array,array+10);
3.方法
調(diào)用push_back函數(shù),表示將元素添加至其尾部:
判斷是否為空:empty();
獲取大醒氪:size();
訪問:
vector::at(); 越界會(huì)拋出exception磨澡,但效率不如operator;
vector::operator[]; 不做邊界檢查质和,但訪問效率高稳摄;
刪除:
clear:清除整個(gè)vector;
pop_back:彈出vector尾部元素饲宿;
erase:刪除vector中某一位置的元素
用法一:指定刪除某一元素厦酬,v.erase(it+1); //t位置+1的位置的元素;
用法二:刪除指定的滿足某條件的瘫想;
對(duì)象里面重載了operator()的話仗阅,調(diào)用方法像函數(shù)一樣;
- Deque
能存放任意型別的雙向隊(duì)列国夜,新增了兩個(gè)方法:
push_front: 在頭部插入一個(gè)元素减噪;
pop_front: 在頭部彈出一個(gè)元素;
5.List
存放任意型別的雙向鏈表(double linked list); 有next和prev指針指向前一個(gè)和后一個(gè)元素车吹; 頭文件list和名稱空間std筹裕;
優(yōu)勢(shì): 彈性,可以隨意插入和刪除元素窄驹,只需要改變next和prev的指針鏈接朝卒; 對(duì)于移動(dòng)元素到另一個(gè)list,沒有發(fā)生復(fù)制乐埠;
劣勢(shì): 只能以連續(xù)的方式存取list中的元素抗斤,查找任意元素的平均時(shí)間和list長度成線性比例; 對(duì)于查找饮戳、隨機(jī)存取等元素定位操作豪治,效率低; 在每個(gè)元素節(jié)點(diǎn)上增加一些較為嚴(yán)重的開銷扯罐,即向前向后兩個(gè)指針负拟;