類型別名,auto,decltype
阿新 • • 發佈:2018-12-02
1、類型別名
類型別名是某種型別的同義詞。
1 int main() 2 { 3 typedef char *ps; // ps是型別char*的別名 4 const ps p1 = 0; // p1是指向char的常量指標 5 const ps *p2; // p2是一個指標,它的物件是指向char的常量指標 6 return 0; 7 }
注意:遇到使用了類型別名的宣告語句時,人們往往會錯誤地嘗試把類型別名替換成它本來的樣子去理解,這種理解方法是錯誤的;要將類型別名看成是一個基本資料型別去理解。
2、auto型別說明符
使用auto型別說明符能讓編譯器替我們去分析表示式所屬的型別。編譯器推斷出來的
1 int main() 2 { 3 /* 4 當引用被用作初始值時,真正參與初始化的其實是引用的物件的值, 5 此時編譯器以引用物件的型別作為auto的型別。 6 */ 7 auto i = 0, &r = i; 8 auto a = r; // a是一個整數 9 /* 10 auto一般會忽略掉頂層const,底層const會保留下來 11 */ 12 const int ci = i, &cr = ci;13 auto b = ci; // b是一個整數(ci的頂層const特效被忽略掉了) 14 auto c = cr; // c是一個整數(cr是ci的別名,ci本身是一個頂層const) 15 auto d = &i; // d是一個整型指標 16 auto e = &ci; // e是一個指向常量的指標(對常量物件取地址是一種底層const) 17 /* 18 如果希望推斷出的auto型別是一個頂層const,需要明確指出 19 */ 20 const auto f = ci; // ci的推演型別是int,f是const int 21/* 22 可以將引用的型別設為auto,此時原來的初始化規則仍然使用;設定一個型別 23 為auto的引用時,初始值中的頂層const仍然保留。如果我們給初始值繫結一個引用, 24 則此時的常量就不是頂層const了。 25 */ 26 auto &g = ci; // g是一個整型常量引用,繫結到ci 27 //auto &h = 42; // 錯誤:不能為非常量引用繫結字面值 28 const auto &j = 42; // 可以為常量引用繫結字面值 29 return 0; 30 }
3、decltype型別說明符
decltype的作用是選擇並返回運算元的資料型別。在此過程中,編譯器分析表示式並得到它的型別,卻不實際計算表示式的值。
如果decltype使用的表示式是一個變數,則decltype返回該變數的型別(包括頂層const和引用在內)。
1 int main() 2 { 3 const int ci = 0, &cj = ci; 4 decltype(ci) x = 0; // x的型別是const int 5 decltype(cj) y = x; // y的型別是const int &,y繫結到變數x 6 //decltype(cj) z; // 錯誤:z是個引用,必須初始化 7 return 0; 8 }
如果decltype使用的表示式不是一個變數,則decltype返回表示式結果對應的型別。有些表示式將向decltype返回一個引用型別。一般來說,當這種情況發生時,意味著該表示式的結果物件能作為一條賦值語句的左值。如果表示式的內容是解引用操作,則decltype將得到引用型別。
1 int main() 2 { 3 int i = 42, *p = &i, &r = i; 4 decltype(r + 0) b; // 加法的結果是int,因此b是一個未初始化的int 5 //decltype(*p) c; // 錯誤:c是int&,必須初始化 6 return 0; 7 }
對於decltype所用的表示式來說,如果變數名加了一對括號,則得到的型別和不加括號時會有不同。如果decltype使用的是一個不加括號的變數,則得到的結果就是該變數的型別;如果給變數加上了一層或多層括號,編譯器就會把它當成是一個表示式。變數是一種可以作為賦值語句左值的特殊表示式,所以這樣的decltype就會得到引用型別。
1 int main() 2 { 3 int i = 42; 4 //decltype((i)) d; // 錯誤:d是int&,必須初始化 5 decltype(i) e; // e是一個未初始化的int 6 return 0; 7 }