第3章 auto佔位符(C++11~C++17)
3.1 重新定義的auto關鍵字
在C++11中靜態成員變數是可以用auto
宣告並且初始化的,不過前提是auto
必須使用const
限定符。
static const auto x = 5;
遺憾的是,const限定符會導致x
常量化,顯然這不是我們想要的結果。在C++17標準中,對於靜態成員變數,auto
可以在沒有const
的情況下使用。
C++20之前,無法在函式形參列表中使用auto
宣告形參(注意,在C++14中,auto可以為lambda表示式宣告形參)
void fun(auto a) // C++20之前編譯錯誤
{
qDebug() << N;
}
int main()
{
int x = 1;
fun(x);
}
3.2 推導規則
1.如果auto
宣告的變數是按值初始化,則推匯出的型別會忽略cv限定符;
2.使用auto
宣告變數初始化時,目標物件如果是引用,則引用屬性會被忽略;
3.使用auto
和萬能引用宣告變數時(見第6章),對於左值會將auto
推導為引用型別;
4.使用auto
宣告變數,如果目標物件是一個陣列或者函式,則auto
會被推導為對應的指標型別;
5.當auto關鍵字與列表初始化組合時,這裡的規則有新老兩個版本,這裡只介紹新規則(C++17標準)。
(1)直接使用列表初始化,列表中必須為單元素,否則無法編譯,auto
型別被推導為單元素的型別。
(2)用等號加列表初始化,列表中可以包含單個或者多個元素,auto
型別被推導為std::initializer_list
,其中T
是元素型別。請注意,在列表中包含多個元素的時候,元素的型別必須相同,否則編譯器會報錯
3.3 什麼時候使用auto
簡單歸納auto的使用規則。
1.當一眼就能看出宣告變數的初始化型別的時候可以使用auto
。
2.對於複雜的型別,例如lambda表示式、std::bind等直接使用auto
。
3.4 返回型別推導【C++14】
C++14標準支援對返回型別宣告為auto
的推導,例如:
auto l = [](auto a1, auto a2) { return a1 + a2; };
3.5 lambda表示式中使用auto型別推導
在C++14標準中我們還可以把auto寫到lambda表示式的形參中,這樣就得到了一個泛型的lambda表示式
起初在後置返回型別中使用auto是不允許的,但是後來人們發現,這是唯一讓lambda表示式透過推導返回引用型別的方法了
傳入引數型別(auto& i
),後置返回型別(-> auto&
),接收結果的變數(auto& j
)必須都是&,才能正確的返回引用。
auto lamda1 = [](auto& i) -> auto& { return i;};
auto& j = lamda1(s);
3.6 非型別模板形參佔位符【C++17】
C++17標準對auto關鍵字又一次進行了擴充套件,使它可以作為非型別模板形參的佔位符。
template<auto N>
void f()
{
qDebug() << N;
}
int main()
{
f<5>();
f<'c'>();
f<5.6>(); // 書上說編譯錯誤 但是在Qt6.7 + MSVC2019 + C++17下透過了編譯
}
3.7 結構化繫結【C++17】
對結構體的結構化繫結(structured bindings),這是C++17標準中引入的特性。
將物件的成員繫結到變數上,從而可以更方便地訪問這些成員。
struct A {
int a;
double b;
};
int main() {
auto a = A{ .a = 1, .b = 2.0 };
auto [x, y] = a;
qDebug() << x << " " << y; // 輸出: 1 2
return 0;
}