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

歡迎訪問 生活随笔!

生活随笔

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

c/c++

STL学习小记--与C++模板相关的几个特性

發布時間:2025/5/22 c/c++ 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 STL学习小记--与C++模板相关的几个特性 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

先談談模板在我腦子里的典型吧

template<class T> const T& GetMax(const T& t1, const T& t2) {return t1>t2?t1:t2; }

如上面的代碼,這是一個模板函數(template function)。要使用這個函數,傳入的參數必須滿足>運算符的條件。在C#中有where關鍵字,很可惜C++的模板沒有這種限制。

而據說BS本人也一再聲明C++的模板不需要這種限制,作為一個初學者,其中緣由就不得而知了。

template并非一次編譯便生成適合所有類型的代碼,而是針對被使用的某個(組)類型進行編譯。這導致一個很嚴肅的問題:實際處理template的時候,面對template function,必須先提供一個實際的例子,然后才能調用,這樣才能通過編譯。所以使用template function的話,需要將整個函數定義在頭文件中,在別處使用也需要提供源碼。C++標準中似乎有對于使template運行可移植性的方法(編譯成dll),但是貌似我使用的編譯器都不支持。

模板和宏在功能上相似,這類的問題經常引起大神們的口水戰,吾輩且避之。

下面登記下模板中使用的幾個特性:

1, Nontyoe Template?Parameters(非類型模板參數)

第一次遇到這個是在學習STL的bitset的時候。后來發現很多書在引入這內容的時候都是拿bitset舉例。

bitset<32> bs32;

作為初學者的我,剛見到的時候非常疑惑,原來模板還有這種用法,可是這種方式來初始化構造的話,為什么不直接用構造函數呢?就像是建一個32長度的數組一樣的方式啊。

可是,32長度的數組不是一個類型,同樣,用構造函數創建的32長度容器也不是某一類型,而是某一類型的實例。而bitset<32>則是一個類型,檔次果然就不一樣了呀。

即是說,如果繼續聲明一個bitset<32> bs32X;那么bs32X和bs32的類型是一樣的,用RTTI來鑒別,typeid就是一樣的。這樣bs32和bs32X是允許相互賦值的。

而如果聲明一個bitset<33> bs33; 那就不是同一類型了。

嗯,模板類是在類級別,而一個是在實例級別,檔次呀檔次。。。

2,Default Template Parameters(缺省模板參數)

C++允許函數有缺省參數, 很方便地, 也允許模板參數有缺省值

比如下例:

template <class T, class NT= int> class P { public:T m_t;NT m_nt; };

這樣在使用的時候,即使只是定義

void f() {P<int> p; //... }

這樣也會被默認為P<int, int>的類型。很方便地特性,和函數缺省參數一樣,能減少不少代碼量。

3, typename

定義一個模板類或是模板函數的時候,需要制定類型的名字,使用T似乎已經是一種潛規則了。

而T前面可以使用typename,也可以使用class來表示后面的標識符是一個類型名。

而關鍵字typename還可以被用來作為類型前的標識符號。

比如:

template <class T> class P {typename T::MyType* pT; };

如果不使用typename關鍵字,按照C++的一般規則,除了typename修飾之外的任何template中的標識符都被視為一個值而非一個類型,所以編譯器就會認為MyType是T中的一個成員,這一行被解釋為MyType和pT相乘。調用語句寫在類定義中編譯器就要報錯了。

使用上面的類模板,傳入的模板參數必須滿足類型中定義了MyType類型,可以使用typedef,可以直接定義class。

4, Member Template(成員模板函數)

全局函數可以是一個template, 同樣C++也允許類成員函數是一個template。但是這樣的成員函數不能使虛函數,而且也不能有缺省參數。(話外音:那不就是一個帶this指針參數的全局函數而已嗎?)

比如:

class A { public:template<class T>void f(T t){//... } };

然后使用的時候只需要實例化一個A類型的變量就能對各種適用的類型使用f函數了。f函數的具體實現不影響A類型,相當方便。

另外需要提到的是,這個特性常常會被用來作為模板類之間類型轉換。

如同在第一個特性中提到的,根據模板參數的不同,類型也會不同,比如MyClass<int>和MyClass<double>屬于兩個不同的類型,那么兩者之間是不能直接轉換的,即使int可以轉換為double。為了滿足這種懶惰成性的需求,就可以使用這個特性。

如下代碼:

template <class T> class A { public:T m_value;A():m_value(){}A(const T& t){m_value = t;}template<class T2>void Parse(const A<T2>& t){this->m_value = t.m_value;} };int main() {A<int> a1(102);A<double> a2(12.222);A<char> a3('a');a1.Parse(a2);cout<<a1.m_value<<endl;//輸出12a2.Parse(a3);//字符'a'將轉化為ASCII碼cout<<a2.m_value<<endl;//輸出97system("pause"); }

其實這里既然是int轉double,那么也可以做成直接用a1來初始化a2。也就是在a2的構造函數中使用a1作為參數。(話外: 構造函數也是成員函數,滿足非虛函數亦沒有缺省參數的條件)

template <class T> class A { public:T m_value;A():m_value(){}A(const T& t){m_value = t;}template<class T2>A(const A<T2>& t){m_value = t.m_value;} };int main() {A<int> a1(97);A<int> a2(a1);A<char> a3(a1);cout<<a1.m_value<<endl;//97cout<<a2.m_value<<endl;//97cout<<a3.m_value<<endl;//asystem("pause"); }

這里a2構造的時候調用的是默認的拷貝構造函數,而a3構造的時候使用的是模板拷貝構造函數。

5, Nested Template(嵌套模板類)

?類中定義的函數可以是模板函數,類中定義的嵌套類也可以是個模板類。

template <class T> class MyClass {//... public:template <class T2>class NestedClass{//... }; };

另外的注意點

面試題是個很有意思的東西,往往能遇到許多稀奇古怪的狀況。以前曾在面試中遇到這樣的問題:

int* pI = new int;

int* pI2 = new int();

上面兩行代碼有什么區別。

我大學匯編是玩NDS上課的,所以無法從那個方向去分析。只是根據實際使用來猜想, 前者分配了空間卻沒有初始化值,后者分配了空間并初始化值。

這和下面的情況相似(貌似使用自定義類型的時候不一定了):

int i;        //undefined value

int i2 = int(); ?//initialized with zero

這是基本類型int,那么自定義類型呢?

自定義的class有時候不會顯式地定義一個構造函數。

struct XX {//XX():n(){}int n; };int main() {XX* pX1 = new XX;XX* pX2 = new XX();cout<<pX1->n<<", "<<pX2->n<<endl; }

輸出的結果是一個未初始化的值和0

那如果自定義的類型已經有一個無參構造函數了呢?那就會調用這個無參構造函數來初始化了。

所以,以后一定要養成定義一個無參構造函數并初始化成員的好習慣啊%>_<%

那么,使用模板的時候呢,使用這個語法可以保證該類型實例能被初始化為一個確切的初值。

摘自:ISO/IEC 14882:2003(E) 5.3.4 - 15
— If the new-initializer is omitted:
??????— If T is a (possibly cv-qualified) non-POD class type (or array thereof), the object is default-initialized(8.5). If T is a const-qualified type, the underlying class type shall have a user-declared default constructor.
??????— Otherwise, the object created has indeterminate value. If T is a const-qualified type, or a (possibly cv-qualified) POD class type (or array thereof) containing (directly or indirectly) a member of const-qualified type, the program is ill-formed;
— If the new-initializer is of the form (), the item is value-initialized (8.5);

?

?

?

轉載于:https://www.cnblogs.com/pasoraku/archive/2013/04/12/3016782.html

總結

以上是生活随笔為你收集整理的STL学习小记--与C++模板相关的几个特性的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。