[深入理解C++11:C++11新特性解析與應用] 學習筆記
auto 類型推導
auto聲明變量的類型由編譯器在編譯時期推導而得。
基本用法:
int main() { double foo(); auto x = 1; //x的類型為int auto y = foo(); //y的類型為double struct m { int i; }str; auto str1 = str; //str1的類型為struct m auto z; //無法推導,無法通過編譯 }
auto使用細則:
1. auto類型指示符與指針和引用之間的關系
在C++11中,auto可以與指針和引用結合起來使用,示例如下:
int x; 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(); //int auto &h = bar(); //int&
本例中,a、c、d的類型都是指針類型,且都指向變量x。實際上,對於a、c、d三個變量而言,聲明為 auto * 或 auto 並沒有區別。而如果要使得auto聲明的變量是另一個變量的引用,則必須使用 auto &,如同本例中的變量b和h一樣。
2. auto 與 valatile 和 const 之間的聯系
volatile 和 const 代表了變量的兩種不同的屬性:易失性和常量的。在C++標准中,它們常常被一起叫作cv限制符(cv-qualifier)。C++11標准規定 auto 可以與cv限制符一起使用,不過聲明為 auto的變量病不能從其初始化表達式中“帶走” cv限制符。示例如下:
double foo(); float *bar(); const auto a = foo(); //a: const double const auto &b = foo(); //b: const double & volatile auto *c = bar(); //c: valatile float * auto d = a; //d: double auto &e = a; //e: const dbouel & auto f = c; //f: float * volatile auto &g = c; //g: volatile float * &
本例中,我們可以通過非cv限制的類型初始化一個cv限制的類型,如變量a、b、c所示。不過通過auto聲明的變量d、f卻無法帶走a和c的常量性或者易失性。這里的例外還是引用,聲明為引用的變量e、g都保持了其引用的對象相同的屬性(事實上,指針也是一樣的)。
3. 同一個賦值語句中,auto 可以用來聲明多個變量的類型,不過這些變量的類型必須相同。如果這些變量的類型不相同,編譯器則會報錯。事實上,用 auto 來聲明多個變量類型時,只有第一個變量用於 auto 的類型推導,然后推導出來的數據類型被作用於其他的變量。
auto x = 1, y = 2; //x和y的類型均為int //m是一個指向const int類型變量的指針,n是一個int類型的變量 const auto *m = &x, n = 1; auto i = 1, j = 3.14f; //編譯失敗
4. C++11新引入的初始化列表,以及new,都可以使用auto關鍵字
auto x = 1; auto x1(1); auto y{1}; //使用初始化列表的auto auto z = new auto(1); //用於new
5. 不能使用 auto 推導的4種情況(編譯器報錯)
1)auto 不能用於函數形參類型。
2)對於結構體來說,非靜態成員變量的類型不能是 auto 的。
3)auto 能不聲明數組類型。
4)在實例化模版的時候不能使用 auto 作為模版參數。
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數組,無法通過編譯 vector<auto> v = {1}; //4:auto模版參數(實例化時),無法通過編譯 }