? ? ? ? C++ Primer第二章的內容主要介紹了變量和基礎類型,包括C++語言定義的基礎內置類型、變量的定義及聲明、符合類型如指針及引用的介紹和const及常量表達式constexpr的介紹,本次博客也從這四個方面進行系統的介紹,如果有不足之處,還望其他博主留言指正;如果博客對你有一定的幫助,還請點個贊支持一下。
1)基本內置類型
? ? ? ? ? C++語言具有廣泛的數據類型,除了基本內置類型之外,還定義了一些復雜的數據類型,比如可變長字符串string和向量vector等,另外也為碼農提供了自定義數據類型的機制,比如類和結構體等,本次博客主要是介紹C++語言中的基本內置類型。
? ? ? ? ? C++將基本內置類型分為算術類型和空類型(void),算術類型又分為整數類型和浮點數類型,其中整數類型又分為布爾類型(bool 未定義最小尺寸大小,值為true或false),字符類型(char,最小尺寸為8位),short類型(最小尺寸為16位),int類型(最小尺寸為16位),long類型(最小尺寸為32位),long long類型(C++11中新定義的,最小尺寸為64位);另外浮點型包括單精度浮點型(32位,有效位數為5位)和雙精度浮點型(64位,有效位數為7位),且浮點數在計算機中的儲存結構如下圖所示:
? ? ? ? ?
? ? ? C++中定義一個char類型的大小和一個機器字節一樣長,同時定義byte(long long)>=byte(long)>=byte(int)>=byte(short)。
? ? ? 在選擇數據類型的時候有以下四條建議:1)合理使用無符號類型,避免無符合和有符號數混合運算;2)整型定義盡量使用int,如果數據較大則使用long long;3)算術表達式盡量不要出現bool和char類型;4)浮點運算選用double類型。
2)初始化及賦值和聲明及定義
? ? ? 初始化和賦值時兩個完全不同的概念,初始化的含義是創建變量時并對變量賦予一個初始值,其調用的是定義好或默認的構造函數,而賦值的含義是將對象當前的值擦除,并用一個新值來替代,調用的是拷貝構造函數或=重載操作符函數。
? ? ? 如果變量只是定義但沒有指定初值,系統會對變量進行默認初始化。對于內置類型變量的默認初始化值,和其位置有關。如果內置類型變量定義在任何函數之外,則默認初始化為0;如果定義在函數內部,則不會被初始化,此時的值未定義,拷貝和訪問沒有定義的值會發生錯誤。絕大多數類都支持默認初始化,這和類中是否有默認構造函數有關,有一些其他的類則需要顯示進行初始化。
? ?? C++規定,可以采用初始化列表的形式來初始化變量,即采用一組由花括號括起來的值來初始化變量,但是需要注意的是使用初始化列表的形式初始化內置類型變量時,如果初始化過程中存在數據截斷的情況,如把一個浮點數賦值給整數,編譯器會報錯。
? ? ?C++為了方便程序實現分離式編譯(可以理解成.C和.h文件的獨立),將聲明和定義區分開。聲明的目的是為了讓變量的名字為程序所知,聲明中只規定變量的類型和名字,并在前面加上extern關鍵字(但不能對加了extern關鍵字的變量進行初始化,否則extern關鍵字失效);定義的目的則是為了創建和名字有關的實體,為變量申請內存空間,還可能初始化變量。
? ? ?建議:不管是在函數內還是函數外,使用內置類型都要初始化。在函數體內部初始化一個由extern關鍵字標記的變量,會發生錯誤,因為變量只能定義一次,但可以多次聲明。
3)指針及引用
? ? ? 指針是一種指向其他類型對象的復合類型(基本數據類型+一組聲明符),大多數情況下需要滿足定義的指針類型和指針指向對象的類型匹配(兩種特殊情況:1)常量指針指向非常量對象。2)virtual類的動態編譯)。指針是一個對象,可以進行賦值和拷貝,也可以指向不同的對象,同時不需要在定義的時候進行賦值(和引用的區別)。使用指針時,如果需要分析程序執行的每個時間段指針的指向,可以采用內存四區模型和一個建議(指針指向誰,就把誰的地址賦給指針)來進行分析。
? ? 對于指針而言,指針的值存在四種狀態:1)指向一個對象(一般情況);2)指向緊鄰對象的一個空間(尾后迭代器);3)空指針,沒有指向任何對象;4)無效指針,除1)2)3)情況之外。
? ? 建議:對于使用了指針的情況下,要判斷所得到的指針是否有效,訪問和拷貝無效指針的值會使程序崩潰。
? ? 引用是指對象的別名,一般情況下的引用都指的是左值引用。引用定義的機制是將引用和變量對象綁定起來,使得引用稱為變量的另外一個名字,但是此時的變量對象可以不初始化。由于定義引用需要將引用和變量對象進行綁定,因此引用必須初始化,且一旦綁定了一個對象,引用就不能再綁定另外一個對象了。引用不是對象,它只是變量對象的一個別名,因此不能定義引用的引用或指向引用的指針。由于引用是和變量對象是綁定起來的,因此通常情況下引用的類型和綁定對象的類型要一致(除了兩種情況:1)初始化常量引用,可以采用任意表達式作為初始值,只要能夠轉換成引用類型;2)virtual類的動態編譯)。
4)const和常量表達式constexpr
? ? ? const限定符的作用是用于限制變量的類型。一般情況下有兩種情況:1)默認情況下,const對象只能在文件內有效。多個文件出現相同的const變量時,等同于不同文件中獨立定義的const變量。2)當const變量初始值不是一個常量表達式且需要實現多個文件共享變量,需要在一個文件中定義const變量,其他文件中聲明并使用它(聲明和定義變量時都需要加上extern const標識符)。
? ? ? 常量引用:也稱為對const的引用,是將引用綁定到const對象上。C++規定允許將非常量的對象,字面量和一般表達式綁定給一個常量引用,只要右端的值能夠轉化為引用的類型即可。但是,在不同類型轉換的過程中,其實引用綁定的是一個臨時量,而非我們希望綁定的那個數據,具體例子如下所示:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?double var=3.14;? ? ? ------------>? ? ? ? ?const int temp=var;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?const int &p=var;? ? ? _______>? ? ? ? ? const int &p=temp;
? ? ?建議:使用引用綁定對象時,養成引用和綁定對象類型一致的習慣。
? ? ?常量表達式(constexpr)指的是值不會改變且在編譯過程中能夠得到計算結果的表達式。一般來說,可以使用算術類型,引用和指針等字面值類型的變量來初始化常量表達式。除此之外,可以地址固定不變的對象來初始化常量表達式。對于constexpr類型的指針初始值必須為nullptr(0)、存儲于某個固定地址的對象或超出函數范圍之外的變量(如static和global變量)。
? ? C++11規定可以采用constex來驗證變量的值是否為常量表達式,初始化常量表達式的值必須為常量或constexpr函數。
***知識點補充1:字,字節和位的區別?
? ? ?位:即bit,是計算機用來存儲數據的最小單元,取值為0或1;
? ? ?字節:即byte,是計算機可尋址的最小內存塊,一個字節等于8bit;(牽涉到的知識點:定義數據的大小)
? ? ?字:即word,是計算機存儲的基本單元,通常由幾個字節組成;(牽涉到的知識點:數據對齊方式和計算機的位數)
***知識點補充2:變量,對象和值之間的關系?
? ? 變量:提供一個具體名字的,可供程序操作的存儲空間。
? ? 對象:具有某種類型的內存空間(數據類型+內存空間)。
? ? 值:只讀的數據。
? ? 已命名的對象才稱為變量。
***知識點補充3:變量的命名規則?
? ? 變量的命名規則有以下四個建議:1)變量名體現實際含義;2)變量名一般使用小寫;3)自定義的類名以大寫字母開頭;4)如果出現多個單詞,單詞之間采用下劃線連接。
***只是補充點4:指向常量的指針/引用,常量指針,頂層const,底層const區別?
? ? 指向常量的指針/引用:指針指向的/引用綁定的對象為常量,此時不能用指針/引用去改變常量對象的值。
? ? 指針常量:指針的地址不變,指向的對象數據可以發生改變,必須初始化。
? ? 頂層const:定義的對象是常量(如常量指針,常量內置定義類型);
? ? 底層const:定義對象指向的值或者綁定的值為常量(如指針常量,指向常量的引用);