auto 指定符(C++11 起)
對於變量,指定其類型將從其初始化器自動推導而出。
對於函數,指定其返回類型是尾隨的返回類型或將從其 return 語句推導出 (C++14 起)。
對於非類型模板形參,指定其類型將從參數推導出。 (C++17 起)
語法
auto variable initializer | (1) | (C++11 起) | |||||||
auto function -> return type | (2) | (C++11 起) | |||||||
auto function | (3) | (C++14 起) | |||||||
decltype(auto) variable initializer | (4) | (C++14 起) | |||||||
decltype(auto) function | (5) | (C++14 起) | |||||||
auto :: |
(6) | (概念 TS) | |||||||
cv(可選) auto ref(可選) parameter | (7) | (C++14 起) | |||||||
template < auto Parameter > |
(8) | (C++17 起) | |||||||
cv(可選) auto ref(可選) [ identifier-list ] initializer ; |
(9) | (C++17 起) | |||||||
解釋
1) 在塊作用域、命名空間作用域、循環初始化語句等中聲明變量時,關鍵詞 auto 可用作類型指定符。
只要初始化器的類型被確定,則編譯器會用來自函數調用的模板實參推導規則所決定的類型替換關鍵詞 auto (細節見模板實參推導)。關鍵詞 auto 可與修飾符組合,如 const 或 & ,它們將參與類型推導。例如,給出 const auto& i = expr; , i
的類型恰是虛構模板 template<class U> void f(const U& u) 中參數 u
的類型,倘若函數調用 f(expr) 被編譯。從而, auto&& 可根據初始化器被推導成左值或是右值引用,這被用於基於范圍的for循環。
2) 在使用尾隨返回類型語法的函數聲明中,關鍵詞 auto 不進行自動類型檢測。它只作為語法的一部分起作用。
4) 若變量的聲明類型是 decltype(auto) ,則關鍵詞 auto 被替換成其初始化器的表達式(或表達式列表),而實際類型以 decltype 規則推導。
5) 若函數返回值的聲明類型為 decltype(auto) ,則關鍵詞 auto 被替換成其返回語句的運算數,而其實際返回類型以 decltype 規則推導。
6) 擁有形式 auto:: 的嵌套名稱指定符是占位符,它會被類或枚舉類型遵循制約類型占位符推導規則替換。
7) lambda 表達式中的參數聲明。 (C++14 起)函數參數聲明。 (概念 TS)
8) 若模板形參聲明為
auto
,則其類型由對應使用參數推導出。
9) 結構化綁定聲明
注意
C++11 前, auto 擁有存儲期指定符的語義。
不允許在一個聲明中混合 auto
變量和函數,如 auto f() -> int, i = 0; 。
示例
運行此代碼
#include <iostream>
#include <utility> template<class T, class U> auto add(T t, U u) { return t + u; } // 返回類型是 operator+(T, U) 的類型 // 在其所調用的函數返回引用的情況下 // 函數調用的完美轉發必須用 decltype(auto) template<class F, class... Args> decltype(auto) PerfectForward(F fun, Args&&... args) { return fun(std::forward<Args>(args)...); } template<auto n> // C++17 auto 形參聲明 auto f() -> std::pair<decltype(n), decltype(n)> // auto 不能從花括號初始化器列表推導 { return {n, n}; } int main() { auto a = 1 + 2; // a 的類型是 int auto b = add(1, 1.2); // b 的類型是 double static_assert(std::is_same_v<decltype(a), int>); static_assert(std::is_same_v<decltype(b), double>); decltype(auto) c1 = a; // c1 的類型是 int ,保有 a 的副本 decltype(auto) c2 = (a); // c2 的類型是 int& ,為 a 的別名 std::cout << "a, before modification through c2 = " << a << '\n'; ++c2; std::cout << "a, after modification through c2 = " << a << '\n'; auto [v, w] = f<0>(); // 結構化綁定聲明 auto d = {1, 2}; // OK : d 的類型是 std::initializer_list<int> auto n = {5}; // OK : n 的類型是 std::initializer_list<int> // auto e{1, 2}; // C++17 起錯誤,之前為 std::initializer_list<int> auto m{5}; // OK : C++17 起 m 的類型為 int ,之前為 initializer_list<int> // decltype(auto) z = { 1, 2 } // 錯誤: {1, 2} 不是表達式 // auto 常用於無名類型,例如 lambda 表達式的類型 auto lambda = [](int x) { return x + 3; }; // auto int x; // 於 C++98 合法, C++11 起錯誤 // auto x; // 於 C 合法,於 C++ 錯誤 }
可能的輸出:
a, before modification through c2 = 3 a, after modification through c2 = 4