C++ 模板浅谈
引言與概述
C++模板機制允許在定義類,函數(shù),類型別名的時候?qū)㈩愋突蛑诞斪鲄?shù),這樣定義的類和函數(shù)在運行時間和空間效率上并不遜色于手工打造的非通用的代碼。
模板提供的代碼是類型安全的。
模板是一種編譯時期的機制,與手工編寫的代碼相比,并不會產(chǎn)生任何運行期開銷。
對模板來說,只有當一個成員函數(shù)被使用時才會被生成代碼。
一個通用的組件應(yīng)該從一個或多個具體實例泛化而來,而不是簡單的從第一原理直接而來。 即我們可以先寫一個具體的函數(shù)或者類,然后改成泛化類型。
模板簡介
一個簡單的模板
template <typename C> class String { public:String();explicit String(const C* c);//..... private:static const int short_max = 15;//用于短字符串的優(yōu)化int sz;C* ptr; };一個模板類的聲明與普通class的聲明差別不大,只需要添加關(guān)鍵字和將需要泛化的類型進行替換。
模板成員函數(shù)也可以不用定義在類內(nèi),也可以在外部定義,但模板成員函數(shù)本身還是一個模板,所以要顯式聲明一個模板:
template<typename C> String<C>::String(): sz(0),ptr(nullptr) {}模板實例化
模板實例化:從一個模板和一個模板實參列表生成一個類或者一個函數(shù)的過程。
{String<char> str; }即可以進行變量的聲明,注意這里我們只創(chuàng)建了對象,即這個類型String< char > 編譯器會為其生成默認構(gòu)造函數(shù)和析構(gòu)函數(shù),不使用的成員對象或者函數(shù)則不會生成。
模板提供了一種用少量代碼來生成大量代碼的機制,但我們要小心實例代碼的泛濫,造成內(nèi)存的大量占用。
通過組合模板和簡單內(nèi)聯(lián)可以消除很多直接或者間接函數(shù)調(diào)用的開銷。
模板參數(shù)
模板機制的最大弱點是無法直接表達對模板參數(shù)的要求。
template <Container Cont, typename Elem>requires Equal_comparable<Cont::value_type, Elem>() int find_index(Cont& c, Elem e);但我們可以這寫來進行模板參數(shù)的檢查。
在C++20 出現(xiàn)了concept這種技術(shù),可以幫助我們進行對模板參數(shù)要求的檢查。
但這種檢查是在編譯過程中非常晚的時刻進行的,而且是在抽象層次很低的層次上運行的,幫助有限。
成員類型別名
如果我們想要在類外使用模板參數(shù),目前只有使用成員類型別名這種方法:
template <typename C> class String { public:using value_type = T; };static成員
一個static的成員只有被真正使用時才被定義。
template <typename T> struct X {static int a;static int b; }; int* p = &X<int>::a;如果這就是全部代碼,那么 a 會被報錯為無定意,而b就不會。
模板與virtual
模板成員函數(shù)不能是虛函數(shù),如果使用那么為虛函數(shù)實現(xiàn)的傳統(tǒng)技巧虛表就很難使用,并且鏈接器的復(fù)雜性也會很高。
模板與嵌入類型
在模板中盡量避免嵌入類型,除非它們真正依賴所有的模板參數(shù)。
模板與友元
template <typename T> class B;template <typename T> void A(const B<T>& b);template <typename T> class B { public:friend void A<>(const B<T>& b); };友元后面的<>是必須的,它指明了友元是一個模板函數(shù),如果沒有<>,則友元函數(shù)被假定為非模板函數(shù)。友元函數(shù)只有被使用時才會被實例化。
友元的設(shè)計目的是為了表達一小群緊密相關(guān)的概念,如果友元關(guān)系很復(fù)雜,那么一定是一個設(shè)計錯誤。
源碼組織
使用模板組織源碼有三種很明顯的方法:
- 在一個編譯單元中,在使用模板前包含其定義;
- 在一個編譯單元中,在使用模板前(只)包含其聲明。在模板稍后的位置(或者使用之后)包含模板定義;
- 在一個編譯單元中,在使用模板前(只)包含其聲明。在其他編譯單元中包含其定義。
很遺憾的是C++并不支持第三種實現(xiàn)方式。
如果一個類模板的布局或者是一個內(nèi)聯(lián)函數(shù)模板的定義發(fā)生了改變,那么使用該類或者該函數(shù)的代碼都要重新編譯。
建議
沒事的,不論未來如何,太陽一定都會升起!沒事的,不論未來如何,太陽一定都會升起!沒事的,不論未來如何,太陽一定都會升起!
總結(jié)
- 上一篇: umeng推送, 生产环境deviceT
- 下一篇: C++ 虚函数和虚表