var i = 10; // 隱式(implicitly)型別定義
int i = 10; // 顯式(explicitly)型別定義
auto i = 10;
是不是和 C# 的隱式型別定義很像呢?auto x = 5; // OK: x是int型別 auto pi = new auto(1); // OK: pi被推導為int* const auto *v = &x, u = 6; // OK: v是const int*型別,u是const int型別 static auto y = 0.0; // OK: y是double型別 auto int r; // error: auto不再表示儲存型別指示符 auto s; // error: auto無法推匯出s的型別在上面的程式碼範例中:
=6
,否則編譯器不予通過。u=6.0
,編譯器將會報錯:
const auto *v = &x, u = 6.0;
error: inconsistent deduction for 'const auto': 'int' and then 'double'
auto int i = 0; // C++98/03,可以預設寫成 int i = 0;
static int j = 0;
int x = 0; auto * a = &x; // a -> int*,auto被推導為int auto b = &x; // b -> int*,auto被推導為int* auto & c = x; // c -> int&,auto被推導為int auto d = c; // d -> int ,auto被推導為int const auto e = x; // e -> const int auto f = e; // f -> int const auto& g = x; // e -> const int& auto& h = g; // f -> const int&由上面的例子可以看出:
template <typename T> void func(T x) {} // T -> auto template <typename T> void func(T * x) {} // T * -> auto * template <typename T> void func(T & x) {} // T & -> auto & template <typename T> void func(const T x) {} // const T -> const auto template <typename T> void func(const T * x) {} // const T * -> const auto * template <typename T> void func(const T & x) {} // const T & -> const auto &
void func(auto a = 1) {} // error: auto不能用於函數引數 struct Foo { auto var1_ = 0; // error: auto不能用於非靜態成員變數 static const auto var2_ = 0; // OK: var2_ -> static const int }; template <typename T> struct Bar {}; int main(void) { int arr[10] = {0}; auto aa = arr; // OK: aa -> int * auto rr[10] = arr; // error: auto無法定義陣列 Bar<int> bar; Bar<auto> bb = bar; // error: auto無法推匯出模板引數 return 0; }在 Foo 中,auto 僅能用於推導 static const 的整型或者列舉元(因為其他靜態型別在 C++ 標準中無法就地初始化),雖然 C++11 中可以接受非靜態成員變數的就地初始化,但卻不支援 auto 型別非靜態成員變數的初始化。
#include <map> int main(void) { std::map<double, double> resultMap; // ... std::map<double,double>::iterator it = resultMap.begin(); for(; it != resultMap.end(); ++it) { // do something } return 0; }觀察上面的疊代器(iterator)變數it的定義過程,總感覺有點憋屈。其實通過 resultMap.begin(),已經能夠知道 it 的具體型別了,卻非要書寫上長長的型別定義才能通過編譯。
#include <map> int main(void) { std::map<double, double> resultMap; // ... for(auto it = resultMap.begin(); it != resultMap.end(); ++it) { // do something } return 0; }再次觀察 it 的定義過程,是不是感到清爽了很多?
#include <map> int main(void) { std::unordered_multimap<int, int> resultMap; // ... std::pair< std::unordered_multimap<int,int>::iterator, std::unordered_multimap<int, int>::iterator > range = resultMap.equal_range(key); return 0; }這個 equal_range 返回的型別宣告顯得煩瑣而冗長,而且實際上並不關心這裡的具體型別(大概知道是一個 std::pair 就夠了)。這時,通過 auto 就能極大的簡化書寫,省去推導具體型別的過程:
#include <map> int main(void) { std::unordered_multimap<int, int> map; // ... auto range = map.equal_range(key); return 0; }另外,在很多情況下我們是無法知道變數應該被定義成什麼型別的,比如下面的例子。
class Foo { public: static int get(void) { return 0; } }; class Bar { public: static const char* get(void) { return "0"; } }; template <class A> void func(void) { auto val = A::get(); // ... } int main(void) { func<Foo>(); func<Bar>(); return 0; }在這個例子裡,我們希望定義一個泛型函數 func,對所有具有靜態 get 方法的型別 A,在得到 get 的結果後做統一的後續處理。若不使用 auto,就不得不對 func 再增加一個模板引數,並在外部呼叫時手動指定 get 的返回值型別。