最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解C++ 模板編程

 更新時(shí)間:2020年09月08日 15:10:01   作者:tlanyan  
模板(template)是C++實(shí)現(xiàn)泛型(Generics)和元編程(Meta Programming)的基礎(chǔ)。本文拋磚引玉,簡(jiǎn)要介紹C++模板編程,不足之處敬請(qǐng)指正。

類(lèi)型模板

類(lèi)型模板包括函數(shù)模板和類(lèi)模板,基本上是C++開(kāi)發(fā)人員接觸模板編程的起點(diǎn)。

下面代碼演示了函數(shù)模板和類(lèi)模板的使用方法:

// 函數(shù)模板
template<typename T>
T add(const T& a, const T& b) {
 return a + b;
}

// 類(lèi)模板
template<typename T>
class Point {
private:
 T x[3];
 ...
};

類(lèi)型模板以template開(kāi)始聲明,尖括號(hào)內(nèi)的typename關(guān)鍵字可用class替代。類(lèi)型模板中typenameclass具有相同含義,均表示參數(shù)類(lèi)型。實(shí)踐中typename語(yǔ)義更廣泛,表示其后續(xù)的參數(shù)T是一個(gè)類(lèi)型,不限定于類(lèi),建議使用。類(lèi)型參數(shù)T可換成其他任意有意義的合法變量。

C++14新增變量模板:

// 變量模板
template<tyepename T>
constexpr T pi = T(3.1415926535897932385L);

尖括號(hào)之于模板猶如小括號(hào)之于函數(shù):函數(shù)通過(guò)小括號(hào)()定義和調(diào)用,模板使用尖括號(hào)<>定義(需template關(guān)鍵字聲明)和實(shí)例化。上面演示了類(lèi)型模板定義,下面代碼介紹模板實(shí)例化:

int a = 1, b = 2;
// 實(shí)例化函數(shù)模板
std::cout << "add result:" << add<int>(a, b) << std::endl;

// 實(shí)例化類(lèi)模板
auto p = Point<int>();

double radius = .5;
// 實(shí)例化變量模板
auto area = pi<double> * radius * radius;

同函數(shù)一樣,模板可以有默認(rèn)值:

// 默認(rèn)類(lèi)型為int
template<typename T=int>
T add(const T& a, const T& b) {
 return a + b;
}

// 默認(rèn)類(lèi)型為double
template<typename T=double>
class Point {
private:
 T x[3];
 ...
};

與函數(shù)不同,對(duì)于函數(shù)模板,如果能從參數(shù)推斷出模板類(lèi)型,則可略去尖括號(hào)模板實(shí)例化參數(shù):

int a = 1, b = 2;
// 合法調(diào)用,編譯器能根據(jù)a b推斷出參數(shù)類(lèi)型
std::cout << "add result:" << add(a, b) << std::endl;
// 等同于
std::cout << "add result:" << add<int>(a, b) << std::endl;

然而對(duì)于類(lèi)模板,即使有默認(rèn)參數(shù),也不能省略尖括號(hào)(但是可以省去參數(shù)):

template<typename T=double>
struct Point {
 T x[3];
};

// 合法聲明
auto p = Point<double>();
// 合法聲明,類(lèi)型使用默認(rèn)的double
auto p2 = Point<>();
// 非法聲明,缺少模板調(diào)用標(biāo)志尖括號(hào)
auto p3 = Point();

類(lèi)型參數(shù)模板在實(shí)際中使用最多,STL庫(kù)中vector、map等容器、algorithm中的許多算法都用到了模板。

非類(lèi)型參數(shù)模板

另一類(lèi)常用模板是非參數(shù)模板,用來(lái)替代某個(gè)具體的值。例如:

// N維空間向量
template<int N>
struct Vector {
 double x[N];
};

// 實(shí)例化
auto v = Vector<100>();
...其他操作

需要注意的是,非類(lèi)型參數(shù)模板能使用的類(lèi)型十分有限,只有(signed/unsigned)整數(shù)、char和枚舉這幾種類(lèi)型可用(參考switch語(yǔ)法)。

同類(lèi)型模板一樣,非類(lèi)型參數(shù)模板也可以有默認(rèn)值,但應(yīng)用到類(lèi)模板實(shí)例化也不能省略尖括號(hào)。

類(lèi)型模板和非類(lèi)型參數(shù)模板可以結(jié)合一起用:

template<typename T, int N>
struct Point {
 T x[N];
};

類(lèi)型模板解決了類(lèi)型問(wèn)題,非類(lèi)型參數(shù)模板解決了值的問(wèn)題,實(shí)際中應(yīng)用也十分廣泛。作為遞歸的經(jīng)典場(chǎng)景,斐波那契數(shù)列可以用非類(lèi)型模板解決:

template<int N>
struct Fib {
 static constexpr int value = Fib<N-1>::value + Fib<N-2>::value;
};
// 模板特化
template<>
struct Fib<1> {
 static constexpr int value = 1;
};
// 模板特化
template<>
struct Fib<0> {
 static constexpr int value = 0;
};

// 調(diào)用
std::cout << "Fib(10): " << Fib<10>::value << std::endl;

這個(gè)例子出現(xiàn)了”模板特化”,接下來(lái)介紹。

模板特化/偏特化

定義模板后,希望在特定條件下使用單獨(dú)的模板,這便是模板特化。上文中斐波那契數(shù)列定義的template<int N> struct Fib是母模板,接下來(lái)又定義了0和1兩個(gè)特化模板(子模板),指示編譯器遇到Fib<0>和Fib<1>的情況,使用這兩組單獨(dú)定義。需要注意的是特化模板的template參數(shù)為空,具體模板參數(shù)放到了模板名稱(chēng)處,類(lèi)似于模板實(shí)例化。

對(duì)多個(gè)模板參數(shù)的情形,如果只特化某個(gè)模板參數(shù),便是偏特化。例如:

// 泛型模板定義
template<typename T1, typename T2> struct Add; 
// 特化模板
template<> struct Add<int, int> {...};
// 偏特化模板
template<typename T> struct Add<T, long> {....};

模板特化/偏特化類(lèi)似于函數(shù)重載,能針對(duì)特殊情況進(jìn)行特別處理。

模板匹配與SFINAE

模板特化使得同一個(gè)模板名稱(chēng)有了多個(gè)定義,代碼具體調(diào)用時(shí)會(huì)遇到模板匹配問(wèn)題。理解模板匹配機(jī)制的關(guān)鍵便是SFINAE,這也是進(jìn)階模板編程的必備知識(shí)點(diǎn)。

SFINAE是Substitution failure is not an error的縮寫(xiě),翻譯過(guò)來(lái)便是:匹配(替換)失敗不是錯(cuò)誤。

怎么理解這句話(huà)呢?

對(duì)于上面的斐波那契數(shù)列數(shù)列代碼,編譯器遇到Fib<10>::value的代碼,(可能)先會(huì)嘗試匹配Fib<0>,發(fā)現(xiàn)匹配不上,這是一個(gè)Substitution failure,但不是error,所以編譯器繼續(xù)嘗試其他可能性。接著匹配Fib<1>,同樣發(fā)現(xiàn)匹配不上,忽略這個(gè)Substitution failure繼續(xù)嘗試Fib<N>,OK,這一次沒(méi)問(wèn)題,編譯成功。

如果是Fib<-1>::value,編譯器達(dá)到最大遞歸深度也找不到一個(gè)合適的匹配模板,這是一個(gè)error,因此編譯失敗。

備注:理解上面的話(huà)需要對(duì)編譯過(guò)程稍加了解,編譯過(guò)程會(huì)輸出許多信息,編譯器一般只有遇到error才會(huì)終止編譯,比較常見(jiàn)的warning則不會(huì)。模板匹配中的Substitution可能連warning都算不上,不會(huì)影響編譯器繼續(xù)嘗試匹配

理解SFINAE是看懂稍微深?yuàn)W點(diǎn)模板代碼的基本功,重點(diǎn)便是:不怕你模板多,就怕找不到合適的模板。

兩階段編譯

有了模板(元)編程,C++源碼編譯可以分為前期和后期,構(gòu)成兩階段編譯。前期是模板的天下,編譯器掃描模板實(shí)例化語(yǔ)句,生成運(yùn)算結(jié)果和具體代碼;后期編譯器介入,再編譯生成機(jī)器碼。

模板代碼運(yùn)行在編譯期,因此有如下特點(diǎn):

  • 沒(méi)有實(shí)例化的模板代碼,即使有語(yǔ)法錯(cuò)誤,編譯器也不會(huì)檢查和報(bào)錯(cuò)。對(duì)按代碼行數(shù)考核KPI的C++碼農(nóng),這絕對(duì)是福音,新增template代碼十萬(wàn)行,瞎編亂寫(xiě)都可以,只要不實(shí)例化,永遠(yuǎn)能編譯通過(guò),編譯后的文件大小(一般)不變,也不影響現(xiàn)有代碼運(yùn)行;
  • 對(duì)于常量,編譯前期直接計(jì)算,沒(méi)有運(yùn)行時(shí)開(kāi)銷(xiāo)。上文中的斐波那契數(shù)列值在編譯期便已經(jīng)計(jì)算出來(lái)了;
  • 無(wú)法運(yùn)行期動(dòng)態(tài)調(diào)用代碼。例如下面的要求做不到:
template<int N>
struct Point {double x[N];};
// 根據(jù)輸入動(dòng)態(tài)生成類(lèi),無(wú)法實(shí)現(xiàn)和編譯成功
int n;
std::cin >> n;
auto p = new Point<n>();
  • 模板和多態(tài)/虛函數(shù)(理念)沖突。多態(tài)/虛函數(shù)的關(guān)鍵是運(yùn)行期動(dòng)態(tài)調(diào)用代碼,而模板在編譯期確定,因此兩者理念上是沖突的。所以,如果你想一個(gè)成員函數(shù)既是模板函數(shù),又是虛函數(shù),怎么做實(shí)現(xiàn)預(yù)期?

C/C++編譯有個(gè)預(yù)處理過(guò)程,只是做簡(jiǎn)單字符串替換,沒(méi)有具體運(yùn)算,與模板生成代碼不同

在編譯前期,除了模板代碼被解釋執(zhí)行,其他代碼信息都在,因此模板代碼擁有類(lèi)似反射/自省的能力,這也是C++元編程功能強(qiáng)大的原因之一。

C++11中的變化

C++11帶來(lái)了許多新特性和重大更新,可以認(rèn)為C++11是一門(mén)新的語(yǔ)言。就模板來(lái)說(shuō),主要更新點(diǎn)如下:

1. 可以使用static constexpr int代替早期模板代碼中的enum。網(wǎng)上許多斐波那契數(shù)列代碼都是基于早期C++,一律使用enum方式定義字段;

2. 可以使用using代替typedef。這是using語(yǔ)句能力的重大更新,早期我們定義類(lèi)型或者別名都需要typedef,自C++11開(kāi)始,簡(jiǎn)單使用using就可以達(dá)到相同效果。

3. C++14引入了變量模板,上文已介紹。

模板優(yōu)缺點(diǎn)

上文根據(jù)自己理解和實(shí)踐簡(jiǎn)要介紹了C++模板編程的相關(guān)概念,本節(jié)總結(jié)一下C++模板的優(yōu)缺點(diǎn):

C++模板編程優(yōu)點(diǎn):

  • 減少代碼輸入,提高代碼重用和編程效率;
  • 支持鴨子類(lèi)型(Duck typing)的特性,使用便利,功能強(qiáng)大;
  • 某些情況下能減少運(yùn)行期開(kāi)銷(xiāo);
  • 能實(shí)現(xiàn)元編程,C++高手必備之路;

C++模板編程缺點(diǎn):

  • 語(yǔ)法看起來(lái)是hack黑科技,代碼可讀性差,編寫(xiě)繁瑣;
  • 模板代碼調(diào)試?yán)щy,生成的錯(cuò)誤信息也晦澀難懂。你可以還記得剛開(kāi)始使用STL模板的map等數(shù)據(jù)類(lèi)型報(bào)錯(cuò)的恐怖提示?
  • 編譯時(shí)間增加。

感謝閱讀,歡迎指正!

以上就是詳解C++ 模板編程的詳細(xì)內(nèi)容,更多關(guān)于C++ 模板編程的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C++深淺拷貝和string類(lèi)的兩種寫(xiě)法詳解

    C++深淺拷貝和string類(lèi)的兩種寫(xiě)法詳解

    這篇文章主要為大家詳細(xì)介紹了C++深淺拷貝和string類(lèi)的兩種寫(xiě)法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-03-03
  • 使用C++實(shí)現(xiàn)單鏈表的操作與實(shí)踐

    使用C++實(shí)現(xiàn)單鏈表的操作與實(shí)踐

    在程序設(shè)計(jì)中,鏈表是一種常見(jiàn)的數(shù)據(jù)結(jié)構(gòu),特別是在動(dòng)態(tài)數(shù)據(jù)管理、頻繁插入和刪除元素的場(chǎng)景中,鏈表相比于數(shù)組,具有更高的靈活性和高效性,尤其是在需要頻繁修改數(shù)據(jù)結(jié)構(gòu)的應(yīng)用中,本文將詳細(xì)介紹如何用C++語(yǔ)言實(shí)現(xiàn)一個(gè)面向?qū)ο蟮膯捂湵?并展示完整的代碼示例
    2025-02-02
  • 給喜歡的人用C語(yǔ)言寫(xiě)煙花

    給喜歡的人用C語(yǔ)言寫(xiě)煙花

    你向窗外看煙火,我在窗邊看你,這時(shí),你比煙花好看的多,你的眼眸倒映滿(mǎn)天的煙火,我的瞳孔倒影你閃光的眼色,這時(shí),我比煙花寂寞
    2021-11-11
  • 利用Matlab繪制一個(gè)可愛(ài)的南瓜燈

    利用Matlab繪制一個(gè)可愛(ài)的南瓜燈

    這篇文章主要為大家介紹了如何利用Matlab繪制一個(gè)可愛(ài)的南瓜燈!文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Matlab有一定幫助,需要的可以參考一下
    2022-02-02
  • OpenCV實(shí)現(xiàn)圖像的直線(xiàn)檢測(cè)

    OpenCV實(shí)現(xiàn)圖像的直線(xiàn)檢測(cè)

    這篇文章主要為大家詳細(xì)介紹了OpenCV實(shí)現(xiàn)圖像直線(xiàn)檢測(cè)的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-01-01
  • C/C++時(shí)間庫(kù)chrono的使用總結(jié)

    C/C++時(shí)間庫(kù)chrono的使用總結(jié)

    std::chrono是C++標(biāo)準(zhǔn)庫(kù)中的一個(gè)組件,用于表示和處理時(shí)間,其功能就像是心理學(xué)中的感知系統(tǒng),它可以為我們捕捉、量化并操作抽象的時(shí)間概念,這就如同我們的大腦可以理解和感知周?chē)h(huán)境的時(shí)間流逝一樣,這種感知和理解能力是人類(lèi)進(jìn)行日?;顒?dòng)所必需的,
    2023-12-12
  • c++實(shí)現(xiàn)值機(jī)系統(tǒng)

    c++實(shí)現(xiàn)值機(jī)系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了c++實(shí)現(xiàn)在線(xiàn)值機(jī)系統(tǒng)程序,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • 深入解析C++中的指針數(shù)組與指向指針的指針

    深入解析C++中的指針數(shù)組與指向指針的指針

    以下是對(duì)C++中的指針數(shù)組與指向指針的指針進(jìn)行了詳細(xì)的介紹,需要的朋友可以過(guò)來(lái)參考下
    2013-09-09
  • 使用C++調(diào)用Python代碼的方法詳解

    使用C++調(diào)用Python代碼的方法詳解

    這篇文章主要介紹了使用C++調(diào)用Python代碼并給大家介紹了.py和.pyc的區(qū)別,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-02-02
  • Qt編寫(xiě)地圖實(shí)現(xiàn)省市區(qū)域圖的示例代碼

    Qt編寫(xiě)地圖實(shí)現(xiàn)省市區(qū)域圖的示例代碼

    本文主要介紹了Qt編寫(xiě)地圖實(shí)現(xiàn)省市區(qū)域圖的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-12-12

最新評(píng)論

西吉县| 区。| 邻水| 大足县| 合水县| 平果县| 溧水县| 马尔康县| 东兰县| 安图县| 盖州市| 南宁市| 静海县| 安吉县| 潼关县| 额尔古纳市| 克山县| 衡阳市| 黎平县| 敖汉旗| 吴江市| 涞水县| 呼伦贝尔市| 西藏| 西青区| 安龙县| 武功县| 科尔| 栾城县| 桃园县| 永和县| 高碑店市| 南宫市| 科尔| 淮滨县| 北海市| 广昌县| 德兴市| 泾阳县| 陈巴尔虎旗| 云安县|