前言
在11
標準之前,auto
在c++
中是聲明存儲器類型的關鍵字。而在11
標準中它的功能變為了類型推導。
對此, 在這里引入C++primer
中的原句:
編程時常常需要把表達式的值賦給變量,這就要求在聲明變量的時候清楚的知道表達式的類型。然而要做到這一點并非那么容易,有時候甚至根本做不到。為了解決這個問題,C++11
新標準引入了auto
類型說明符,用它就能讓編譯器替我們去分析表達式所屬的類型。和原來的那些對應的一種特定類型的說明符不同,auto
讓編譯器通過初始值來推斷變量的類型。顯然,auto
定義的變量必須具有初始值。
比如下面的代碼:
?vector<int> vtr{ 0, 1, 2, 3, 4 };for (auto x : vtr)cout << x << ' ';
可以看出auto
設計的基本思想就是想通過簡短的auto
占位符替代程序中長且雜的各種數據類型。從而增大開發效率。
顯然想要auto
實現這一目的需要滿足——auto
必須能夠表示出程序中的所有數據類型。
auto
的組合使用
auto
不僅僅能夠表示單獨的數據類型,還可以和&
,*
等類型標識符配合使用組成其他的數據類型,比如:
?int x = 0;auto *pt1 = &x; // pt1為int*, auto推導為 intauto pt2 = &x; // pt2為int*, auto推導為int*auto& r1 = x; // r1為int&, auto推導為intauto r2 = r1; // r2為int,auto推導為int
指針和引用作為棧區數據的左膀右臂,若只使用auto
關鍵字,想要達到將int
賦值給引用這種操作顯然是做不到的。
int
在賦值給auto
時會不明確auto
到底是普通類型還是引用類型而產生二義性,為了避免二義性,規定int
類型賦值給auto
依舊是int
類型,若想要賦值給引用類型需要auto
和&
配合使用。
這也與auto
表示所有類型的理念不約而和。
auto
與const
前面講述和auto
在設計時為了避免二義性會進行取舍操作,保證一種聲明賦值語句只會對應一種類型。
但是這樣同樣會衍生一個問題——在避免二義性得時候如何選擇。
假設我們作為C++
語言的設計者,在選擇時肯定會更偏向于更自由的一方,畢竟C++
的設計理念就是既想保留C
的自由,又想發展自己的東西。
接下來我就會列舉幾個auto
個const
的組合。并從是否合法,涵蓋全面,更自由的選擇等方面來分析編譯器為何會如此選擇。
要補充一點,可能有的時候看似auto
有多種選擇,因為在C++
中賦值語句是支持隱式類型轉換的,但是實際上auto
作為"萬能的數據類型",其在設計時就應當規避掉類型轉換的操作,所以在分析時我不會考慮類型轉換的選擇。
?int x = 0;const auto n = x; // auto會被推導為 intauto f = n; // const在取值時沒有限定,因此編譯器會將auto處理為int,顯然int會比const int涵蓋面更廣?const auto& r1 = x; // auto會被翻譯成int, 當然也有可能會被翻譯成const int, 不過在編譯器中多個const和一個const效果相同?// int& r3 = n; 這樣賦值編譯器會報錯auto& r2 = n; // r2會被翻譯成const int, 因為const int數值是不能賦值給int引用的,所以編譯器選擇const int
-
const auto n = x
:x
為int
類型,而auto
前面有const
限定符,顯然這里的auto
只能被推導為int
類型。 -
auto f = n
:前面我們分析了n
為const int
類型,而const int
類型允許賦值給const int
,和int
類型,有兩種選擇,最終選擇int
。主要從兩方面分析,一方面是我們所說的自由性,若想要賦值給
const int
類型可以在auto
前加上const
限定符。而
const int
無法添加限定符將其變為int
類型,所以顯然int
要比const int
更自由。另一方面,如果
auto
在這里被推導為const int
類型,那么你會發現沒有一種情況可以使const int
類型賦值給auto
時auto
被推導為int
了,這違背了auto
的設計理念。 -
const auto& r1 = x
:會被翻譯為int
,不多討論。 -
auto& r2 = n
:n
為const int
類型,而在c++
中只允許const int
類型賦值給const int&
類型(這里不是說不能賦值給其他,只是說若要賦值給引用則必須加const
限定符),所以這里也只能是const int&
。
總結
借用C++primer
中的一句話:
auto
一般會忽略掉頂層const
,同時底層const
則會保留下來。
比如在a = b
這種賦值語句中,盡管b
有const
限定,但其實a
是直接將b
中的數據拷貝過來,auto
會直接忽略掉const
。
而在&a = b
這種語句中,a
實際上是保存的b
的地址,auto
就會保留下const
。