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