1.傳統(tǒng)C++ VS 現(xiàn)代C++
傳統(tǒng)C++中,參數(shù)的類(lèi)型都必須明確定義,這其實(shí)對(duì)我們快速進(jìn)行編碼沒(méi)有任何幫助,尤其是當(dāng)我們面對(duì)一大堆復(fù)雜的模板類(lèi)型時(shí),必須明確的指出變量的類(lèi)型才能進(jìn)行后續(xù)的編碼,這不僅拖慢我們的開(kāi)發(fā)效率,也讓代碼變得又臭又長(zhǎng)。
C++11 引入了類(lèi)型推導(dǎo),讓編譯器來(lái)操心變量的類(lèi)型。這使得 C++ 也具有了和其他現(xiàn)代編程語(yǔ)言一樣,某種意義上提供了無(wú)需操心變量類(lèi)型的使用習(xí)慣。
下面代碼中CoderWorld(1,"Traditional","C++")是傳統(tǒng)C++寫(xiě)法而CoderWorld(2,"Modern","C++")是現(xiàn)代C++寫(xiě)法,雖然使用了模板,但是其用法就像調(diào)用沒(méi)有使用模板的普通函數(shù)一樣,這樣的代碼明顯更加具有易讀性。這是因?yàn)镃++11引入了類(lèi)型推導(dǎo),編譯器會(huì)自動(dòng)推導(dǎo)出參數(shù)的類(lèi)型。
template
2.模板類(lèi)型參數(shù)推導(dǎo)
模板類(lèi)型參數(shù)推導(dǎo)共分為四種情況,下面會(huì)分別對(duì)這四種情況進(jìn)行詳細(xì)闡述。
- 函數(shù)形參的類(lèi)型為指針或引用類(lèi)型,但不是通用引用類(lèi)型
- 函數(shù)形參的類(lèi)型為通用引用類(lèi)型
- 函數(shù)形參的類(lèi)型既不是指針也不是引用
- 數(shù)組或函數(shù)名
模板類(lèi)型推導(dǎo)案例1
template<typename T>
void CoderWorld(T& param);
int x = 27;
const int& rx = x;
CoderWorld(rx); // T is const int, param's type is const int&
上述代碼中函數(shù)CoderWorld(T& param)中形參的類(lèi)型是引用類(lèi)型(即T&), 推導(dǎo)遵循的規(guī)則如下:
在函數(shù)形參的類(lèi)型為指針或引用類(lèi)型,但不是通用引用類(lèi)型情況下,需要去掉實(shí)參類(lèi)型中的引用(這里的去掉引用是指去掉實(shí)參類(lèi)型的引用,而不是形參param的類(lèi)型T&中的&)。
對(duì)于CoderWorld(rx),實(shí)參rx為const int&類(lèi)型,根據(jù)上述應(yīng)該去掉實(shí)參rx 類(lèi)型的引用,即將const int&中的&去掉,因此T被推導(dǎo)為const int 類(lèi)型,最終param的類(lèi)型T&為const int &類(lèi)型。
模板類(lèi)型推導(dǎo)案例2
template<typename T> void CoderWorld(T&& param);
int x = 27;
const int cx = x;
const int& rx = x;
CoderWorld(cx);//cx is lvale,so T is const int&, param's type is const int&
CoderWorld(27);//27 is rvale,so T is int,param's type is int&&
上述代碼中函數(shù)CoderWorld(T&& param) 形參類(lèi)型是通用引用類(lèi)型(即T&&),推導(dǎo)規(guī)則遵循如下:
在函數(shù)形參的類(lèi)型為通用引用類(lèi)型情況下,當(dāng)實(shí)參的類(lèi)型是左值時(shí),param的類(lèi)型和T的類(lèi)型均為左值引用,當(dāng)實(shí)參的類(lèi)型是右值時(shí),T的類(lèi)型與實(shí)參一致,param的類(lèi)型是實(shí)參類(lèi)型的右值引用。
代碼中cx是一個(gè)左值,因此T的類(lèi)型與形參param的類(lèi)型均推導(dǎo)為左值引用const int &。
當(dāng)CoderWorld傳入的參數(shù)是27時(shí),因?yàn)?7是右值,所以T的類(lèi)型推導(dǎo)為int,param的類(lèi)型推導(dǎo)為右值引用int&&
模板類(lèi)型推導(dǎo)案例3
template<typename T> void CoderWorld(T param);
const int cx = x;
const int& rx = x;
CoderWorld(cx);//T and param are both int
CoderWorld(rx);// T and param are both int
上述代碼中CoderWorld(T param)形參類(lèi)型T即不是指針也不是引用類(lèi)型,實(shí)際上是值傳遞,也就是說(shuō)這種情況下形參param是實(shí)參的一個(gè)拷貝,推導(dǎo)規(guī)則遵循如下:
在函數(shù)形參的類(lèi)型既不是指針也不是引用類(lèi)型的情況下,如果實(shí)參的類(lèi)型有引用,則忽略掉引用部分,如果實(shí)參類(lèi)型有const,則忽略掉const部分,如果有volatile也忽略掉。
代碼中實(shí)參cx的類(lèi)型為const int,因此忽略掉const之后T的類(lèi)型為int,形參param的類(lèi)型也為int。
代碼中實(shí)參rx的類(lèi)型為const int &,去掉引用和const之后T的類(lèi)型為int,形參param的類(lèi)型也為int。
模板類(lèi)型推導(dǎo)案例4
這是一種特殊的情況,就是當(dāng)實(shí)參的類(lèi)型是為數(shù)組和函數(shù)的時(shí)候需要注意。C++中,數(shù)組可以退化成指針,一個(gè)函數(shù)類(lèi)型也是可以退化成指針的。具體的情況如下代碼所示,結(jié)合注釋記住這段代碼中的CoderWorld1和CoderWorld2對(duì)數(shù)組和函數(shù)的推導(dǎo)情況即可。
template<typename T>
void CoderWorld1(T param);
template <typename T>
void CoderWorld2(T& param);
int arr = {0,1,2,3};
void someFunc(int,double);
CoderWorld1(arr);//arr會(huì)退化成指針,即param的類(lèi)型為int*
CoderWorld2(arr);//這里很有意思,param會(huì)被推導(dǎo)為 int (&)[4]
//和上面的情況相比好處是param包含了數(shù)組的元素?cái)?shù)量信息,可以獲取到數(shù)組的成員數(shù)。
CoderWorld1(someFunc);//param類(lèi)型為函數(shù)指針 void (*)(int,double)
CoderWorld2(someFunc);//param類(lèi)型為函數(shù)引用 void (&)(int,double)
3.模板類(lèi)型推導(dǎo)總結(jié)
參數(shù)類(lèi)型 | 例子 | 推導(dǎo)規(guī)則 |
---|---|---|
指針或引用類(lèi)型,但不是通用引用類(lèi)型 | template void CoderWorld(T& param);void CoderWorld(T* param); | 忽略實(shí)參引用 |
通用引用類(lèi)型 | templatevoid CoderWorld(T&& param); | 實(shí)參為左值param為左值引用實(shí)參為右值param為右值引用 |
既不是指針也不是引用 | templatevoid CoderWorld(T param); | 忽略引用和const類(lèi)型 |
數(shù)組或函數(shù)名 | CoderWorld(arr)CoderWorld(someFunc) | 數(shù)組退化為指針函數(shù)退化為函數(shù)指針image |
-
參數(shù)
+關(guān)注
關(guān)注
11文章
1859瀏覽量
32427 -
編碼
+關(guān)注
關(guān)注
6文章
957瀏覽量
54951 -
C++
+關(guān)注
關(guān)注
22文章
2114瀏覽量
73857
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論