模板的簡單介紹
C++中模板是為了能夠使得函數或者類實現范型編程的目的, 同時C++模板的出現是為了避免代碼的冗余
舉個例子
void Swap(int& a, int& b)
{int tmp = a;b = a;a = b;
}
void Swap(char& a, char& b)
{char tmp = a;b = a;a = b;
}
上面的函數除了類型不同以外, 其他都可以看成是完全形同的, 但是由于代碼不支持范型編程, 所以我們就必須將不同的類型都實現一遍.為了避免這種代碼冗余, 于是就出現的模板.
其中模板可以分為函數模板和類模板
函數模板
template <class T>
void swap(T& a, T& b)
{T tmp = a;a = b;b = a;
}
void TestSwap()
{swap(1, 2);
}
編譯器在執行上述代碼的時候就會根據實參的不同自動推演出類型, 然后將自己的類型傳給對應的 T, 此時編譯器也就直到了參數的類型
注意 編譯器在進行類型實例化的時候如果有現成的類型符合自己(不用經過推演), 那么編譯器就會去調用現成的函數, 當沒有現成的函數給自己調用的時候, 但是有模板函數, 此時編譯器就會是使用模板生成一份
模板類
template <class T>
class Vector
{
public:Vector();~Vector();Vector(const Vector <T>& v);Vector& operator = (const Vector <T>& v);void Reserve(size_t size);void ReSize(size_t size, const T& value = T());const T& operator [] (size_t pos) const;void Insert(size_t pos, const T& x);void PushFront(const T& x);void PushBack(const T& x);void Erase(size_t pos);size_t Capacity();bool Empty();size_t Size();void PopBack();void PopFront();
protected:void Expand(size_t size);
protected:T* _start;T* _finish;T* _endofstorage;
};
上面代碼就是通過模板類實現Vector的各種操作. 在使用模板類的時候, 當模板類成員函數定義在類體外的時候, 此時應該注意, 書寫格式和原來的就會有所不同, 用上面Vector這個模板類來做個比方吧
template <class T>
Vector& Vector <T>::operator = (const Vector <T>& v)
{...
}
小知識點總結
模板相關
模板在經過實例化之后才會生成指令. 編譯器在進行編譯的時候只會對模板的外殼進行語法檢查不會對它的內容進行檢查
Vector增容做了哪些事情
Vector在增容的時候它會做兩件事情, 第一件事情就是進行動態內存開辟. 當開辟完內存之后, 它會看一下此時的類型是自定義類型還是內置類型, 如果是自定義類型就將原來空間上的內容直接memcpy拷貝給新開辟的這片空間, 然后釋放原來的內存空間. 當發現此時的類型是一個自定義類型的時候, 此時就要進行深拷貝, 具體做法就是申請一片新的空間, 然后利用循環將原來空間中的值重新復制給新的這片空間, 最后釋放原來的空間
自動定義類型之為什么需要深拷貝
加入此時的類型是一個sring類型, 當進行擴容的時候編譯器會給其分配一個新的空間, 此時當我們定義出來一個對象的時候, 如果出了作用域對象就要析構,當進行析構的時候, 加入我們只是進行了簡單的memcpy此時新開辟的空間中的string指向原來的空間, 但是當我們memcpy完之后就會對其進行釋放, 然而此時由于對象出了作用域就要進行析構, 此時就會出現對一個野指針進行銷毀, 當然會出錯