日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++ 模板浅谈

發(fā)布時間:2023/12/13 c/c++ 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++ 模板浅谈 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

引言與概述

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ù)的代碼都要重新編譯。

建議

  • 使用模板用于很多實參類型的算法
  • 用模板表示容器
  • 注意template < class T>和template < typename T>意義相同
  • 當設(shè)計一個模板時,首先設(shè)計和調(diào)試非模板版本,隨后添加參數(shù)將其泛化
  • 模板是類型安全的,但檢查的時機太晚了
  • 當設(shè)計一個模板時,仔細思考concept,它對模板參數(shù)的要求
  • 如果一個類模板必須是可拷貝的,則為它定義一個非模板的拷貝構(gòu)造函數(shù)和拷貝復(fù)制運算符
  • 如果一個類模板必須是可移動的,則為它定義一個非模板的移動構(gòu)造函數(shù)和移動復(fù)制運算符
  • 虛函數(shù)不能是成員模板函數(shù)
  • 只有當一個類型,依賴類模板的所有實參時才將其定義為模板成員
  • 使用函數(shù)模板推斷類模板實參類型
  • 對多種不同的實參類型,重載函數(shù)模板來獲得相同語義
  • 借助實參帶入失敗機制為程序提供正確的候選函數(shù)集
  • 使用模板別名簡化符號,隱藏實現(xiàn)細節(jié)
  • C++不支持模板分別編譯,在每個用到模板的編譯單元中都#include模板定義
  • 使用普通函數(shù)作為接口編不能用模板處理的代碼
  • 將大的模板和較嚴重依賴上下文的模板分開編譯
  • 沒事的,不論未來如何,太陽一定都會升起!沒事的,不論未來如何,太陽一定都會升起!

    總結(jié)

    以上是生活随笔為你收集整理的C++ 模板浅谈的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。