C++11新特性中auto 和 decltype 區別和聯絡。本站提示廣大學習愛好者:(C++11新特性中auto 和 decltype 區別和聯絡)文章只能為提供參考,不一定能成為您想要的結果。以下是C++11新特性中auto 和 decltype 區別和聯絡正文
C++11新特性中auto 和 decltype 區別和聯絡
一. auto簡介
編程時分經常需求把表達式的值付給變量,需求在聲明變量的時分清楚的知道變量是什麼類型。但是做到這一點並非那麼容易(特別是模板中),有時分基本做不到。為理解決這個問題,C++11新規范就引入了auto類型闡明符,用它就能讓編譯器替我們去剖析表達式所屬的類型。和原來那些只對應某種特定的類型闡明符(例如 int)不同。auto 讓編譯器經過初始值來停止類型推演。從而取得定義變量的類型,所以說 auto 定義的變量必需有初始值。
//由val_1 和val_2相加的後果可以推斷出item的類型 auto item = val_1 + val_2;//item 類型初始化為val_1 + val_2相加後的類型,值為val_1+val_2相加的值。
這裡的 item 的類型是編譯器在編譯的進程中經過val_1和val_2的類型相加後推算出來的。假設是val_1(int) + val_2(double),那麼item的類型就是double.
運用auto也能在一個語句中聲明多個變量,由於一個聲明雨具只能有一個根本數據類型,所以該雨具一切變量的初始根本數據類型都必需是一樣的。在這裡一定要區別數據類型和類型修飾符!!
int i = 3; auto a = i,&b = i,*c = &i;//正確: a初始化為i的正本,b初始化為i的援用,c為i的指針. auto sz = 0, pi = 3.14;//錯誤,兩個變量的類型不一樣。
編譯器推斷出來的auto類型有時分會跟初始值的類型並不完全一樣,編譯器會適當的改動後果類型使得其更契合初始化規則。
首先,正如我們熟知的,運用援用其實是運用援用的對象,特別當援用被用作初始值的時分,真正參與初始化的其實是援用對象的值。此時編譯器以援用對象的類型作為auto的類型:
int i = 0 ,&r = i;//定義一個整數i,並且定義r為i的使用. auto a = r; //這裡的a為為一個整數,其值跟此時的i一樣.
由此可以看出auto會疏忽援用,其次,auto普通會疏忽掉頂層const,但底層const會被保存上去,比方現在始值是一個指向常量的指針時:
int i = 0; const int ci = i, &cr = ci; //ci 為整數常量,cr 為整數常量援用 auto a = ci; // a 為一個整數, 頂層const被疏忽 auto b = cr; // b 為一個整數,頂層const被疏忽 auto c = &ci; // c 為一個整數指針. auto d = &cr; // d 為一個指向整數常量的指針(對常量對象區地址是那麼const會變成底層const)
假如你希望推斷出auto類型是一個頂層的const,需求明白指出:
const auto f = ci;
還可以將援用的類型設為auto,此時原來的初始化規則依然適用(用於援用聲明的const都是底層const):
auto &g = ci; //g是一個整數常量援用,綁定到ci。 auto &h = 42; // 錯誤:十分量援用的初始值必需為左值。 const auto &j = 42; //正確:常量援用可以綁定到字面值。
二. decltype簡介
有的時分我們還會遇到這種狀況,我們希望從表達式中推斷出要定義變量的類型,但卻不想用表達式的值去初始化變量。還有能夠是函數的前往類型為某表達式的的值類型。在這些時分auto顯得就有力了,所以C++11又引入了第二品種型闡明符decltype,它的作用是選擇並前往操作數的數據類型。在此進程中,編譯器只是剖析表達式並失掉它的類型,卻不停止實踐的計算表達式的值。
decltype(f()) sum = x;// sum的類型就是函數f的前往值類型。
在這裡編譯器並不實踐調用f函數,而是剖析f函數的前往值作為sum的定義類型。
根本上decltype的作用和auto很類似,就不逐個羅列了。關於decltype還有一個用處就是在c++11引入的後置前往類型。
三. decltype 和 auto 區別
decltype在處置頂層const和援用的方式與auto有些許不同,假如decltype運用的表達式是一個變量,則decltype前往該變量的類型(包括頂層const和援用在內)。
const int ci = 42, &cj = ci; decltype(ci) x = 0; // x 類型為const int auto z = ci; // z 類型為int decltype(cj) y = x; // y 類型為const int& auto h = cj; // h 類型為int
decltype還有一些值得留意的中央,我們先來看看上面這段代碼:
int i = 42, *p = &i, &r = i; decltype(i) x1 = 0; //由於 i 為 int ,所以 x1 為int auto x2 = i; //由於 i 為 int ,所以 x2 為int decltype(r) y1 = i; //由於 r 為 int& ,所以 y1 為int& auto y2 = r; //由於 r 為 int& ,但auto會疏忽援用,所以 y2 為int decltype(r + 0) z1 = 0; //由於 r + 0 為 int ,所以 z1 為int, auto z2 = r + 0; //由於 r + 0 為 int ,所以 z2 為int, decltype(*p) h1 = i; //這裡 h1 是int&, 緣由前面講 auto h2 = *p; // h2 為 int.
假如表達式的內容是解援用操作,則decltype將失掉援用類型。正如我們所熟習的那樣,解援用指針可以失掉指針所指對象,而且還可以給這個對象賦值。因而decltype(*p)的後果類型就是int&.
decltype和auto還有一處重要的區別是,decltype的後果類型與表達方式親密相關。有一種狀況需求特別留意:關於decltype 所用表達式來說,假如變量名加上一對括號,則失掉的類型與不加上括號的時分能夠不同。假如decltype運用的是一個不加括號的變量,那麼失掉的後果就是這個變量的類型。但是假如給這個變量加上一個或多層括號,那麼編譯器會把這個變量當作一個表達式對待,變量是一個可以作為左值的特殊表達式,所以這樣的decltype就會前往援用類型:
int i = 42; //decltype(i) int 類型 //decltype((i)) int& 類型
這裡再指出一個需求留意的中央就是 = 賦值運算符前往的是左值的援用。換句話意思就是說 decltype(i = b) 前往類型為 i 類型的援用。細心看上面這段代碼:
int main() { int i = 42; decltype(i = 41) x = i; auto y = i; auto& z = i; printf("i x y z 此時為: %d %d %d %d\n", i,x,y,z); i--; printf("i x y z 此時為: %d %d %d %d\n", i, x, y, z); x--; printf("i x y z 此時為: %d %d %d %d\n", i, x, y, z); y--; printf("i x y z 此時為: %d %d %d %d\n", i, x, y, z); z--; printf("i x y z 此時為: %d %d %d %d\n", i, x, y, z); return 0; }
運轉後果為:
i x y z 此時為: 42 42 42 42 i x y z 此時為: 41 41 42 41 i x y z 此時為: 40 40 42 40 i x y z 此時為: 40 40 41 40 i x y z 此時為: 39 39 41 39
由下面的代碼和運轉後果可以看出來,1.decltype(i = 41)中的賦值語句並沒有真正的運轉。2. decltype(i = 41)前往的其實是int&,也就是說x 其實是 i 的援用。
理解了auto 和 decltype後,當前在運用的進程中一定要分清兩者的區別,避免在定義的時分發生const 與非const 以及援用 與非援用 的差異!!
感激閱讀,希望能協助到大家,謝謝大家對本站的支持!