auto用法
C++98 auto
早在C++98標(biāo)準(zhǔn)中就存在了auto關(guān)鍵字,那時(shí)的auto用于聲明變量為自動(dòng)變量,自動(dòng)變量意為擁有自動(dòng)的生命期,這是多余的,因?yàn)榫退悴皇褂胊uto聲明,變量依舊擁有自動(dòng)的生命期:
int a =10 ; //擁有自動(dòng)生命期 auto int b = 20 ;//擁有自動(dòng)生命期 static int c = 30 ;//延長(zhǎng)了生命期C++98中的auto多余且極少使用,C++11已經(jīng)刪除了這一用法,取而代之的是全新的auto:變量的自動(dòng)類型推斷。
回到頂部
C++11 auto
auto可以在聲明變量的時(shí)候根據(jù)變量初始值的類型自動(dòng)為此變量選擇匹配的類型,類似的關(guān)鍵字還有decltype。舉個(gè)例子:
int a = 10;auto au_a = a;//自動(dòng)類型推斷,au_a為int類型cout << typeid(au_a).name() << endl;typeid運(yùn)算符可以輸出變量的類型。程序的運(yùn)行結(jié)果輸出了
int
這種用法就類似于C#中的var關(guān)鍵字。auto的自動(dòng)類型推斷發(fā)生在編譯期,所以使用auto并不會(huì)造成程序運(yùn)行時(shí)效率的降低。而是否會(huì)造成編譯期的時(shí)間消耗,我認(rèn)為是不會(huì)的,在未使用auto時(shí),編譯器也需要得知右操作數(shù)的類型,再與左操作數(shù)的類型進(jìn)行比較,檢查是否可以發(fā)生相應(yīng)的轉(zhuǎn)化,是否需要進(jìn)行隱式類型轉(zhuǎn)換。
回到頂部
auto的用法
上面舉的這個(gè)例子很簡(jiǎn)單,在真正編程的時(shí)候也不建議這樣來使用auto,直接寫出變量的類型更加清晰易懂。下面列舉auto關(guān)鍵字的正確用法。
用于代替冗長(zhǎng)復(fù)雜、變量使用范圍專一的變量聲明。
想象一下在沒有auto的時(shí)候,我們操作標(biāo)準(zhǔn)庫(kù)時(shí)經(jīng)常需要這樣:
#include<string> #include<vector> int main() {std::vector<std::string> vs;for (std::vector<std::string>::iterator i = vs.begin(); i != vs.end(); i++){//...} }這樣看代碼寫代碼實(shí)在煩得很。有人可能會(huì)說為何不直接使用using namespace std,這樣代碼可以短一點(diǎn)。實(shí)際上這不是該建議的方法(C++Primer對(duì)此有相關(guān)敘述)。使用auto能簡(jiǎn)化代碼:
#include<string> #include<vector> int main() {std::vector<std::string> vs;for (auto i = vs.begin(); i != vs.end(); i++){//..} }for循環(huán)中的i將在編譯時(shí)自動(dòng)推導(dǎo)其類型,而不用我們顯式去定義那長(zhǎng)長(zhǎng)的一串。
在定義模板函數(shù)時(shí),用于聲明依賴模板參數(shù)的變量類型。
template <typename _Tx,typename _Ty> void Multiply(_Tx x, _Ty y) {auto v = x*y;std::cout << v; }若不使用auto變量來聲明v,那這個(gè)函數(shù)就難定義啦,不到編譯的時(shí)候,誰知道x*y的真正類型是什么呢?
模板函數(shù)依賴于模板參數(shù)的返回值
template <typename _Tx, typename _Ty> auto multiply(_Tx x, _Ty y)->decltype(x*y) {return x*y; }當(dāng)模板函數(shù)的返回值依賴于模板的參數(shù)時(shí),我們依舊無法在編譯代碼前確定模板參數(shù)的類型,故也無從知道返回值的類型,這時(shí)我們可以使用auto。格式如上所示。
decltype操作符用于查詢表達(dá)式的數(shù)據(jù)類型,也是C++11標(biāo)準(zhǔn)引入的新的運(yùn)算符,其目的也是解決泛型編程中有些類型由模板參數(shù)決定,而難以表示它的問題。
auto在這里的作用也稱為返回值占位,它只是為函數(shù)返回值占了一個(gè)位置,真正的返回值是后面的decltype(_Tx*_Ty)。為何要將返回值后置呢?如果沒有后置,則函數(shù)聲明時(shí)為:
而此時(shí)x,y還沒聲明呢,編譯無法通過。
回到頂部
注意事項(xiàng)
- auto 變量必須在定義時(shí)初始化,這類似于const關(guān)鍵字。
-
定義在一個(gè)auto序列的變量必須始終推導(dǎo)成同一類型。例如:
auto a4 = 10, a5 = 20, a6 = 30;//正確 auto b4 = 10, b5 = 20.0, b6 = 'a';//錯(cuò)誤,沒有推導(dǎo)為同一類型 使用auto關(guān)鍵字做類型自動(dòng)推導(dǎo)時(shí),依次施加一下規(guī)則: -
如果初始化表達(dá)式是引用,則去除引用語義。
int a = 10; int &b = a;auto c = b;//c的類型為int而非int&(去除引用) auto &d = b;//此時(shí)c的類型才為int&c = 100;//a =10; d = 100;//a =100; -
如果初始化表達(dá)式為const或volatile(或者兩者兼有),則除去const/volatile語義。
const int a1 = 10; auto b1= a1; //b1的類型為int而非const int(去除const) const auto c1 = a1;//此時(shí)c1的類型為const int b1 = 100;//合法 c1 = 100;//非法 -
如果auto關(guān)鍵字帶上&號(hào),則不去除const語意。
const int a2 = 10; auto &b2 = a2;//因?yàn)閍uto帶上&,故不去除const,b2類型為const int b2 = 10; //非法 這是因?yàn)槿绾稳サ袅薱onst,則b2為a2的非const引用,通過b2可以改變a2的值,則顯然是不合理的。 -
初始化表達(dá)式為數(shù)組時(shí),auto關(guān)鍵字推導(dǎo)類型為指針。
int a3[3] = { 1, 2, 3 }; auto b3 = a3; cout << typeid(b3).name() << endl;程序?qū)⑤敵?/p>
int *
-
若表達(dá)式為數(shù)組且auto帶上&,則推導(dǎo)類型為數(shù)組類型。
int a7[3] = { 1, 2, 3 }; auto & b7 = a7; cout << typeid(b7).name() << endl;程序輸出
int [3]
-
函數(shù)或者模板參數(shù)不能被聲明為auto
void func(auto a) //錯(cuò)誤 { //... } -
時(shí)刻要注意auto并不是一個(gè)真正的類型。
cout << sizeof(auto) << endl;//錯(cuò)誤 cout << typeid(auto).name() << endl;//錯(cuò)誤
auto僅僅是一個(gè)占位符,它并不是一個(gè)真正的類型,不能使用一些以類型為操作數(shù)的操作符,如sizeof或者typeid。
總結(jié)
- 上一篇: MFC开发问题
- 下一篇: eclipse创建java web项目