C++ 实现 STL 标准库和算法(二)template 编程和迭代器粗解 实验楼笔记
生活随笔
收集整理的這篇文章主要介紹了
C++ 实现 STL 标准库和算法(二)template 编程和迭代器粗解 实验楼笔记
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
?
一、template 編程和迭代器粗解1.1 實(shí)驗(yàn)內(nèi)容
本節(jié)內(nèi)容主要講述 c++11 模板的用法,以后的代碼中會(huì)大量的用到模板的知識。同時(shí)簡單講解迭代器的相關(guān)知識,為后面容器和算法的內(nèi)容作鋪墊。1.2 實(shí)驗(yàn)知識點(diǎn)
- 模板編程
- 基本語法
- 模板函數(shù)
- 類模板和成員模板
- 模板類中的靜態(tài)成員
- typename和class
- 迭代器
- 迭代器詳解
- 迭代器種類和使用
基本語法
模板編程是 STL 的基石,也是 c++11 的核心特性之一。模板是相對于編譯器而言,顧名思義就是向編譯器提供一個(gè)處理事務(wù)的模板,以后需要處理的東西,如果都是這個(gè)事務(wù)類型,那么統(tǒng)統(tǒng)用這個(gè)模板處理。 三、函數(shù)模板 模板的基本語法如下: template <typename/class T> template 告訴編譯器,接下來是一個(gè)模板 ,typename 和 class 都是關(guān)鍵字,在這里二者可以互用沒有區(qū)別。在< >中?T?叫做模板形參,一旦模板被實(shí)例化,T?也會(huì)變成具體的類型。接下來,我們看一個(gè)例子。 ? 代碼實(shí)例: template <typename T> T add(const T lva ,const T rva) { T a ; a = lva + rva ; return a; } 這是一個(gè)模板函數(shù)的簡單實(shí)例,所有模板函數(shù)在開始都需要?template?語句,以告訴編譯器這是一個(gè)模板和參數(shù)等必要信息,當(dāng)然里面的?T?可以取任意你喜歡的名字 ,模板參數(shù)個(gè)數(shù)也是任意更換的。 還要提醒的一點(diǎn)是:template <typename T1 ,typename T2 = int>函數(shù)模板是支持默認(rèn)參數(shù)的,T1 、T2順序在默認(rèn)情況下是可以任意的,不用嚴(yán)格按照從右到左的順序。 然后就是使用了,我們可以寫出add(1,2)?這樣的函數(shù),也可以寫出add(2.5,4.6)這樣的函數(shù),向?add?函數(shù)提供參數(shù)時(shí),編譯器會(huì)自動(dòng)分析參數(shù)的類型,然后將所有用到 T 定義的換成相對性的類型,以上的兩個(gè)函數(shù)在編譯期間會(huì)生成 int add(const int lva ,const int rva) { int a ; a = lva + rva ; return a; } double add(const double lva ,const double rva) { double a ; a = lva + rva ; return a; } 這樣的兩個(gè)具體函數(shù)。如果我們使用add(1,2.0)是會(huì)報(bào)錯(cuò)的,編譯器無法找到add(int,double)。大家可以自己分析一下為什么。 ? 四、類模板和成員模板?
類模版
c++11 不僅支持對函數(shù)的模板化,也支持對類的模板,下面來看基本的語法是怎樣的: template <class T> class Myclass { T a; public: T add(const T lva ,const T rva); }; template <class T> T Myclass<T>::add(const T lva, const T rva) { a = lva + rva; return a; } 這是一個(gè)簡單并且典型的類模板,在程序中給出模板并不能使用它,還必須實(shí)例化,比如: Myclass<int> A;?//用 int 實(shí)例化一個(gè)類A Myclass<double> B;?//用 double 實(shí)例化一個(gè)類B 當(dāng)程序編譯到這里時(shí)就會(huì)按照我們給出的類型,聲明兩組類和兩組類函數(shù)。注意,在這里我們一定要顯式給出類型 T 。類模板不像是函數(shù)模板 ,函數(shù)模板會(huì)根據(jù)參數(shù)推斷類型。 當(dāng)然類模板也支持默認(rèn)參數(shù),但是類模板必須嚴(yán)格從右往左默認(rèn)化。成員模板
模板的使用范圍是廣泛的,不僅可以用作函數(shù)模板,類模板,還可以用作 class ,struct ,template class 的成員。而要實(shí)現(xiàn) STL 這是我們必須掌握和使用的特性。我們先看一個(gè)簡單的例子,用上面的類改編而來: template <class T> class Myclass { public: T a; template <typename type_1 , typename type_2> type_1 add(const type_1 lva ,const type_2 rva); }; template <class T> template <typename type_1,typename type_2> type_1 Myclass<T>::add(const type_1 lva, const type_2 rva) { a = lva + rva; return a; } 在類的聲明中使用了一個(gè)嵌套的模板聲明。且通過作用域運(yùn)算符?::?指出 add 是類的成員,需要注意的一點(diǎn),有些編譯器不支持模板成員,而有些編譯器不支持在類外定義。我們默認(rèn)大家的編譯器都支持。模板如此強(qiáng)大,甚至允許我們在模板類中再建立模板類: template <class T> class Myclass { public: T a; template <typename type_1 , typename type_2> type_1 add(const type_1 lva ,const type_2 rva); template <class type_3> class Myclass_2; // 聲明放在這里,具體定義放在類外進(jìn)行。 Myclass_2<T> C; // 定義一個(gè)Myclass_2 類 A。使用 T 進(jìn)行實(shí)例化 }; template <class T> template <typename type_1,typename type_2> type_1 Myclass<T>::add(const type_1 lva, const type_2 rva) { a = lva + rva; return a; } template <class T> template <class type_3> class Myclass<T>::Myclass_2 { public: type_3 value; type_3 sub(const type_3 a , const type_3 b) {vlaue = a - b;} }; 當(dāng)然我們暫時(shí)還用不到這樣復(fù)雜的東西,這里只是展現(xiàn)了模板的部分特性。 ? ? 五、模板類中的靜態(tài)成員 ? ? 我們知道,在類中定義的靜態(tài)成員是存儲(chǔ)在靜態(tài)區(qū)中,被所有類對象共享,并不屬于某一個(gè)類所有,同樣的在模板類中的靜態(tài)成員也不會(huì)被復(fù)制多份,而是被同類實(shí)例化的類對象共享,比如所有 int 和所有 double 的類對象,享有相互獨(dú)立的靜態(tài)變量。也可以說是編譯器生成了 int 和 double 兩個(gè)版本的類定義。 ? 六、typename 和 class ? typename和class是模板中經(jīng)常使用的兩個(gè)關(guān)鍵詞 ,在模板定義的時(shí)候沒有什么區(qū)別。以前用的是 class,后來 c++ 委員會(huì)加入了 typename。因?yàn)闅v史原因,兩個(gè)是可以通用的。對有些程序員來說,在定義類模板的時(shí)候,常常使用 class 作為關(guān)鍵字,增加代碼可讀性。其它則用 typename,上面的代碼大都遵循這樣的標(biāo)準(zhǔn),但是并無強(qiáng)制規(guī)定。但是如果二者沒有差別,為什么還要加入typename呢?c++標(biāo)準(zhǔn)委員會(huì)不會(huì)增加無用的特性,讓我們來看一個(gè)例子: class Myclass{ public: Myclass(); typedef int test; //定義類型別名 } template <class T> class Myclass2{ public: Myclass2(); T::test *a // 聲明一個(gè)指向T::test類型的指針。 // typename T::test * a } 以上的代碼沒有全部寫完,大家覺得編譯器能夠過嗎?答案是不能,因?yàn)樵?c++ 中,允許我們在類中定義一個(gè)類型別名,且使用的時(shí)候和類名訪問類成員的方法一樣。這樣編譯器在編譯的時(shí)候就會(huì)產(chǎn)生二義性,它根本不知道這是一個(gè)類型還是別名,所以我們加上 typename 顯式說明出來。當(dāng)然如果這里沒有二義性,比如Myclass ::test * a?,加上 typename 是會(huì)報(bào)錯(cuò)的。此外,在 class 的 STL 底層還有一個(gè)特性,用于保留模板參數(shù),但是在 c++17 中已經(jīng)舍棄,所以我們沒有講。 ? ? 七、實(shí)驗(yàn)總結(jié) ? 模板是 c++ 最重要的特性之一,模板函數(shù)、模板類、類中的模板函數(shù)、類中的模板類、模板類中的模板類等等,可以寫出太多強(qiáng)大的代碼,這也是模板的魅力所在,而 STL 就是基于模板的,大家一定要掌握模板的基本用法。 引用《c++ primer》, 《STL 源碼解析》 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?轉(zhuǎn)載于:https://www.cnblogs.com/hx97/p/11192953.html
總結(jié)
以上是生活随笔為你收集整理的C++ 实现 STL 标准库和算法(二)template 编程和迭代器粗解 实验楼笔记的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: LR使用
- 下一篇: leetcode-139-单词拆分