国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

一、C++11新特性:auto類型推導

gityuan / 2068人閱讀

摘要:宋體關鍵字中的含義宋體不再是一個存儲類型指示符如為純粹類型指示符,而是一個新的類型指示符等是類型指示符來指示編譯器,聲明變量的類型必須由編譯器在編譯時期推導而得。


一、auto類型推導

聲明:該筆記是在學習《深入理解C++11》、《C++11/14高級編程 Boost程序庫探秘》時做的總結,方便以后鞏固復習!

1.1、靜態類型、動態類型和類型推導

靜態類型:C/C++常被成為靜態類型的語言,變量必須被定義;

動態類型:python、Perl、JavaScript語言常被稱為動態類型的語言,變量不需要聲明就可以被使用。

靜態類型和動態類型的區別:是在對變量進行類型檢測的時間點;靜態類型的類型檢測主要發生在編譯階段;動態類型的類型檢測主要發生在運行階段。

動態類型語言變量“拿來就用”的特性依賴的是類型推導技術;事實上類型推導也可以用于靜態類型的語言;C++11中類型推導的實現方式就有兩種:①、auto,②、decltype;先學習auto關鍵字!

auto關鍵字在早期的C/C++標準中的含義:

按照C/C++早期標準,聲明時使用auto修飾的變量,是具有自動存儲的局部變量;幾乎無人使用這種含義,因為一般函數內沒有聲明為static的變量總是具有自動存儲的局部變量。

auto關鍵字C++11中的含義:

auto不再是一個存儲類型指示符(如static、extern為純粹類型指示符),而是一個新的類型指示符(int、float等是類型指示符)來指示編譯器,
auto聲明變量的類型必須由編譯器在編譯時期推導而得。

int main(){	double foo();	auto x = 1; //x的類型為int	auto y = foo(); //y的類型為double	struct m 	{		int i;	}str; 	auto str1 = str;//str1的類型是sturct m	auto z;//無法推導,不能通過編譯}

auto 聲明的變量必須被初始化,以使編譯能夠從其初始化表達式中推導出其類型。這里可以理解為auto并非一種“類型”,而是一個類型聲明時的“占位符”,編譯器在編譯時會將auto替代為變量實際的類型。

1.2、auto的優勢

①、最大優勢就是在擁有初始化表達式的復雜類型變量聲明時簡化代碼

由于C++的發展,聲明變量類型也變得越來越復雜,很多時候,名字空間、模板成為了類型的一部分,導致程序員在使用庫的時候如履薄冰。

#include #incldue <vector>void loopover(std::vector<std:string> & vs){	std::vector<std::string>::iterator i = vs.begin(); //可看出在在不使用u命名空間時,使用iterator 需要書寫大量代碼	for(; i < vs.end(); i++)	{		...	}}

用auto的話,代碼會的可讀性可以成倍增長

#include #incldue <vector>void loopover(std::vector<std:string> & vs){	std::vector<std::string>::iterator i = vs.begin(); 	//使用auto,就不需要書寫大量代碼	for(auto  i = vs.begin(); i < vs.end(); i++)	{		...	}}

②、第二個優勢則在于可以免除程序員在一些類型聲明時的麻煩,或者避免一些在類型聲明時的錯誤

在C/C++中,存在著很多隱式或者用戶自定義的類型轉換規則(比如整型與字符型進行加法運算后,表達式返回的是整型,這是一條隱式規則)。這些規則并非很容易記憶,尤其是在用戶自定義了很多操作符之后。而這個時候,auto就有用武之地了。

class PI{    public:    	double operator* (float v)        {            return (double)val * v;        }    	const float val = 3.1415927f;};int main(){    float radius = 1.7e10;    PI pi;    auto circumference = 2 * (pi * radius);    cout << "circumference = " << circumference << endl;    return 0;}
輸出:circumference = 1.06814e+11

這里定義了float型的變量radius(半徑)以及一個自定義類型PI變量pi(π值),在計算圓周長的時候,使用了auto類型來定義變量circumference。這里,PI在與float類型數據相乘時,其返回值為double。而PI的定義可能是在其他的地方(頭文件里),main函數的程序員可能不知道PI的作者為了避免數據上溢或者精度降低而返回了double類型的浮點數。因此main函數程序員如果使用float類型聲明circumference,就可能享受不了PI作者細心設計帶來的好處。反之,將circumference聲明為auto,則毫無問題,因為編譯器已經自動地做了最好的選擇。

③、第三個優點就是其“自適應”性能夠在一定程度上支持泛型的編程

我們再回到上面代碼例子,這里假設改動了PI的定義,如將operator*返回值變為long double,此時,main函數并不需要修改,因為auto會“自適應”新的類型。

同時,對于不同的平臺上的代碼維護,auto也會帶來一些“泛型”的好處。這里我們以strlen函數為例,在32位的編譯環境下,strlen返回的為一個4字節的整型,而在64位的編譯環境下,strlen會返回一個8字節的整型。雖然系統庫為其提供了size_t類型來支持多平臺間的代碼共享支持,但是使用auto關鍵字我們同樣可以達到代碼跨平臺的效果。

auto v = strlen("hello world!")

由于size_t的適用范圍往往局限于中定義的函數,auto的適用范圍明顯更為廣泛。

當auto應用于模板的定義中,其“自適應”性會得到更加充分的體現。如:

#include using namespace std;template<typename T1, typename T2>double Sum(T1 & t1, T2 & t2){    auto s = t1 + t2;    return s;}int main(){    int a = 3;    long b = 5;    float c = 1.0f, d = 2.3f;    auto e = Sum<int,long>(a,b);//s的類型被推導為long    auto f = Sum<float,float>(c,d);//s的類型被推導為float	cout << e << endl;	cout << f << endl;	return 0;}
輸出:83.3

在上面程序中,由于類型T1、T2要在模板實例化時才能確定,所以在Sum中將變量s的類型聲明為auto的。在函數main中我們將模板實例化時,Sum中的s變量會被推導為long類型,而Sum中的s變量則會被推導為float??梢钥吹?,auto與模板一起使用時,其“自適應”特性能夠加強C++中“泛型”的能力。不過在這個例子中,由于總是返回double類型的數據,所以Sum模板函數的適用范圍還是受到了一定的限制。

④、在宏定義中,避免出現性能問題

#include using namespace std;#define MAX1(a, b) ((a) > (b)) ? (a) : (b)#define MAX2(a, b) ({/        auto _a = (a);/        auto _b = (b);/        (_a > _b) ? _a : _b;})         int main() { 	int m1 = MAX1(1*2*3*4, 5+6+7+8); 	int m2 = MAX2(1*2*3*4, 5+6+7+8); 	cout << m1 << endl; 	cout << m2 << endl;	return 0;  }

定義了兩種類型的宏MAX1和MAX2。兩者作用相同,都是求a和b中較大者并返回。前者采用傳統的三元運算符表達式,這可能會帶來一定的性能問題。因為a或者b在三元運算符中都出現了兩次,那么無論是取a還是取b,其中之一都會被運算兩次。而在MAX2中,我們將a和b都先算出來,再使用三元運算符進行比較,就不會存在這樣的問題了。

在傳統的C++98標準中,由于a和b的類型無法獲得,所以我們無法定義MAX2這樣高性能的宏。而新的標準中的auto則提供了這種可行性。

1.3、auto使用時注意事項

①、auto類型指示符與指針和引用之間的關系

int x = 1;int * y = &x;double foo();int & bar();auto * a = &x; // int*auto & b = x;// int&auto c = y;// int*auto * d = y; // int*//auto * e = &foo();//編譯失敗,指針不能指向一個臨時變量//auto & f = foo();//編譯失敗,nonconst的左值引用不能和一個臨時變量綁定auto g = bar();// intauto & h = bar();// int&

變量a、c、d的類型都是指針類型,且都指向變量x。實際上對于a、c、d三個變量而言,聲明其為auto *或auto并沒有區別。

而如果要使得auto聲明的變量是另一個變量的引用,則必須使用auto &,如同本例中的變量b和h一樣。

②、auto與volatile和const之間也存在著一些相互的聯系

volatile和const代表了變量的兩種不同的屬性:易變的和常量的。

在C++標準中,它們常常被一起叫作cv限制符(cv-qualifier)。鑒于cv限制符的特殊性,C++11標準規定auto可以與cv限制符一起使用,不過聲明為auto的變量并不能從其初始化表達式中“帶走”cv限制符。

double foo();float * bar();const auto a = foo(); //a:const doubleconst auto & b = foo(); //b:const double&volatile auto * c = bar(); //c:volatile float*auto d = a; //d:doubleauto & e = e; //e:const double &auto f = c; //f:float *volatile auto & g = c; //g:volatile float * &

可以看出通過非cv限制的類型初始化一個cv限制的類型,如變量a、b、c所示。不過通過auto聲明的變量d、f卻無法帶走a和f的常量性或者易失性。這里的例外還是引用,可以看出,聲明為引用的變量e、g都保持了其引用的對象相同的屬性(事實上,指針也是一樣的)。

③、auto可以用來聲明多個變量的類型,不過這些變量的類型必須相同

如果這些變量的類型不相同,編譯器則會報錯。事實上,用auto來聲明多個變量類型時,只有第一個變量用于auto的類型推導,然后推導出來的數據類型被作用于其他的變量。

auto x = 1, y = 2;//m是一個指向const int類型變量的指針,n是一個int類型的變量const auto* m = &x, n = 1;//auto i = 1, j = 3.14f; //編譯失敗auto o = 1,&p = o,*q = &p; //從左向右推導

使用auto聲明了兩個類型相同變量x和y,并用逗號進行分隔,這可以通過編譯。而在聲明變量i和j的時候,按照我們所說的第一變量用于推導類型的規則,那么由于x所推導出的類型是int,那么對于變量j而言,其聲明就變成了int j =3.14f,這無疑會導致精度的損失。而對于變量m和n,就變得非常有趣,這里似乎是auto被替換成了int,所以m是一個int *指針類型,而n只是一個int類型。同樣的情況也發生在變量o、p、q上,這里o是一個類型為int的變量,p是o的引用,而q是p的指針。auto的類型推導按照從左往右,且類似于字面替換的方式進行。事實上,標準里稱auto是一個將要推導出的類型的“占位符”(placeholder)。這樣的規則無疑是直觀而讓人略感意外的。當然,為了不必要的繁瑣記憶,程序員可以選擇每一個auto變量的聲明寫成一行(有些觀點也認為這是好的編程規范)。

④、只要能夠進行推導的地方,C++11都為auto指定了詳細的規則,保證編譯器能夠正確地推導出變量的類型

包括C++11新引入的初始化列表,以及new,都可以使用auto關鍵字

 #include  auto x = 1; auto x1(1); auto y {1};      // 使用初始化列表的auto      	auto z = new auto(1);    // 可以用于new       

auto變量y的初始化使用了初始化列表,編譯器可以保證y的類型推導為int。而z指針所指向的堆變量在分配時依然選擇讓編譯器對類型進行推導,同樣的,編譯器也能夠保證這種方式下類型推導的正確性。

⑤、不過auto也不是萬能的,受制于語法的二義性,或者是實現的困難性,auto往往也會有使用上的限制

  #include         using namespace std;        //void fun(auto x =1){}  // 1: auto函數參數,無法通過編譯  struct str{  	//auto var = 10;    // 2: auto非靜態成員變量,無法通過編譯    };  int main() {  char x[3];  auto y = x; // auto z[3] = x; // 3: auto數組,無法通過編譯    // 4: auto模板參數(實例化時),無法通過編譯  vector<auto> v = {1};  }  

①、對于函數fun來說,auto不能是其形參類型??赡茏x者感覺對于fun來說,由于其有默認參數,所以應該推導fun形參x的類型為int型。但事實卻無法符合大家的想象。因為auto是不能做形參的類型的。如果程序員需要泛型的參數,還是需要求助于模板。

②、對于結構體來說,非靜態成員變量的類型不能是auto的。同樣的,由于var定義了初始值,讀者可能認為auto可以推導str成員var的類型為int的。但編譯器阻止auto對結構體中的非靜態成員進行推導,即使成員擁有初始值。

③、聲明auto數組。我們可以看到,main中的x是一個數組,y的類型是可以推導的,而聲明auto z[3]這樣的數組同樣會被編譯器禁止。

④、在實例化模板的時候使用auto作為模板參數,如main中我們聲明的vector v。雖然讀者可能認為這里一眼而知是int類型,但編譯器卻阻止了編譯。

歡迎關注公眾號:Kevin的嵌入式學習站

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/123196.html

相關文章

  • 四、C++11特性:追蹤返回類型

    摘要:四追蹤返回類型宋體聲明該筆記是在學習深入理解高級編程程序庫探秘時做的總結,方便以后鞏固復習引入追蹤返回類型的目的宋體追蹤返回類型配合與會真正釋放中泛型編程的能力簡化函數的定義,提高代碼的可讀性。 ...

    tianyu 評論0 收藏0
  • C++入門篇(2)之引用,內聯函數,auto和范圍遍歷

    文章目錄 前言extern C引用1.概念2.語法3.引用特性4.常量引用5.引用做函數返回值6.引用注意點7.傳值、傳引用效率比較 內聯函數1.概念2.特性 auto關鍵字1.概念2.auto的使用細則3.auto不能推導的場景 基于范圍的for循環(C++11)使用條件 指針空值nullptr 前言 承接上文入門篇1,博主這次將會繼續更新以下內容:extern ,引用 ,內聯, a...

    wangtdgoodluck 評論0 收藏0
  • C++】C++快速入門

    摘要:中包含的即為命名空間的成員。使用輸入輸出更方便,不需增加數據格式控制,比如整形,字符可以連續輸出,表示換行缺省參數備胎,就是給汽車準備一個備用輪胎,一旦那個輪子爆胎或者出了問題,備用輪胎就方便及時地取而代之,汽車就不至于中途拋錨。 ...

    TalkingData 評論0 收藏0
  • [初識C++] 何為最:心酸歷史

    摘要:上面需要了解的是這倆個版本都是破蛹成蝶的版本世界挑戰榜咋才前三還沒擠進去呀,你想想世界上有幾千中編程語言,在其中脫穎出來,可以說是天之嬌子,鳳毛麟角了。支持正版圖靈上面買吧,如果沒錢買盜版吧學完以后買本正版支持一下,創作不易是吧 ...

    forrest23 評論0 收藏0
  • Python學習之路21-序列構成的數組

    摘要:第行把具名元組以的形式返回。對序列使用和通常號兩側的序列由相同類型的數據所構成當然不同類型的也可以相加,返回一個新序列。從上面的結果可以看出,它雖拋出了異常,但仍完成了操作查看字節碼并不難,而且它對我們了解代碼背后的運行機制很有幫助。 《流暢的Python》筆記。接下來的三篇都是關于Python的數據結構,本篇主要是Python中的各序列類型 1. 內置序列類型概覽 Python標準庫...

    ralap 評論0 收藏0

發表評論

0條評論

gityuan

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<