1. 程式人生 > 其它 >《C++ Primer Plus(第6版)》讀書筆記(三)

《C++ Primer Plus(第6版)》讀書筆記(三)

技術標籤:C和C++學習c++

第三章 處理資料

本章內容包括:

  • C++變數的命名規則。
  • C++內建的整型——unsigned long、long、unsigned、int、int、unsigned short、short、char、unsigned char、signed char和bool。
  • C++11新增的整型:unsigned long long和long long。
  • 表示各種整型的系統限制的climits檔案。
  • 各種整型的數字字面值(常量)。
  • 使用const限定符來建立符號常量。
  • C++內建的浮點型別:float、double和long double。
  • 表示各種浮點型別的系統限制的cfloat檔案。
  • 各種浮點型別的數字字面值。
  • C++的算術運算子。
  • 自動型別轉換。
  • 強制型別轉換。

內建的C++型別分兩組:基本型別和複合型別。基本型別,即整數和浮點數。在基本型別的基礎上建立的複合型別,包括陣列、字串、指標和結構。

必須遵循幾種簡單的C++命名規則
(1)在名稱中只能使用字母字元、數字和下劃線。
(2)名稱的第一個字元不能是數字。
(3)區分大寫字元和小寫字元。
(4)不能將C++關鍵字用作名稱。以兩個下劃線或下劃線和大寫字母打頭的名稱被保留給實現(編譯器及其使用的資源)使用。以一個下劃線開頭的名稱被保留給實現,用作全域性識別符號。
(5)C++對於名稱的長度沒有限制,名稱中的所有字元都有意義,但有些平臺有長度限制。

C++提供了一種靈活的標準,它確保了最小長度(從C語言借鑑而來),如下所示:
(1)short至少16位;
(2)int至少與short一樣長;
(3)long至少32位,且至少與int一樣長;
(4)long long至少64位,且至少與long一樣長。

符號常量,前處理器方式。
#define INT_MAX 32767
#define和#include一樣,也是一個前處理器編譯指令,也可以使用#define來定義自己的符號常量,但是#define編譯指令是C語言遺留下來的,C++有一種更好的建立符號常量的方法(使用關鍵字const),所以不會經常使用#define。然而,有些標頭檔案,尤其是那些被設計成可用於C和C++中的標頭檔案,必須使用#define。

使用const的時候,應在宣告中對const進行初始化。const比#define好,首先,它能夠明確指定型別。其次,可以使用C++的作用域規則將定義限制在特定的函式或檔案中(作用域規則描述了名稱在各種模組中的可知程式)。第三,可以將const用於更復雜的型別。
const

C++提供了大量的整型,應使用哪種型別呢?通常,int被設定為對目標計算機而言最為“自然”的長度。自然長度(natural size)指的是計算機處理起來效率最高的長度。如果沒有非常有說服力的理由來選擇其他型別,則應使用int。

整型字面值(常量)是顯式地書寫的常量。與C相同,C++能夠以三種不同的計數方式來書寫整數:基數為10,基數為8(老式UNIX版本)和基數為16(硬體黑客的最愛)。基數為10,第一位為1-9;基數為8,第一位是0,第二位為1-7;基數為16,前兩位為0x或0X。標頭檔案iostream提供了控制符dec、hex和oct,分別用於指示cout以十進位制、十六進位制和八進位制格式顯示整數。

字尾是放在數字常量後面的字母,用於表示型別。

型別縮寫
long、long doublel或L
unsigned intu或U
unsigned longul(可任何一種順序、大寫小寫均可)
long longll或LL
unsigned long longull或Ull或uLL或ULL
floatf或F

任何數字值和指標值都可以被隱式轉換(即不用顯示強制轉換)為bool值。任何非零值都被轉換為true,而零被轉換為false。

C++有兩種書寫浮點數的方式。第一種是使用常用的標準小數點表示法,第二種表示浮點值的方法叫做E表示法,其外觀是像這樣的:3.45E6,這指的是3.45與1000000相乘的結果,E6指的是10的6次方,即1後面6個0,6被稱為指數,3.45被稱為尾數。

C++也有3種浮點型別:float、double和long double。這些型別是按它們可以表示的有效位數和允許的指數最小範圍來描述的。有效位(significant figure)是數字中有意義的位。可以從標頭檔案cfloat或float.h中找到系統的限制。

ostream方法cout.setf(ios_base::fixed, ios_base::floatfield),這種呼叫迫使輸出使用定點表示法,以便更好地瞭解精度,它防止程式把較大的值切換為E表示法,並使程式顯示到小數點後6位。引數ios_base::fixed和ios_base::floatfield是通過包含iostream來提供的常量。通常cout會刪除結尾的零。

與整數相比,浮點數有兩大優點。首先,它們可以表示整數之間的值。其次,由於有縮放因子,它們可以表示的範圍大得多。另一方面,浮點運算的速度通常比整數運算慢,且精度將降低。

求模運算子,餘數,兩個運算元必須都是整數,將該運算子用於浮點數將導致編譯錯誤。如果其中一個是負數,則結果的符號滿足如下規則:(a/b)*b + a%b = a。它與整數除法相結合,尤其適用於解決要求將一個量分成不同的整數單元的問題,例如將英寸轉換成英尺和英寸,或者將美元裝換為元、角、分、釐。

當兩個運算子的優先順序相同時,C++將看運算元的結合性(associativity)是從左到右,還是從右到左。從左到右的結合意味著如果兩個優先順序相同的運算被同事用於同一個運算元,則首先應用左側的運算子。從右到左的結合性則首先應用右側的運算子。

C++自動執行很多型別轉換:將一種算數型別的值賦給另一種算術型別的變數時,C++將對值進行轉換;表示式中包含不同的型別時,C++將對值進行轉換;將引數傳遞給函式時,C++將對值進行轉換。下面是這些規則的詳細介紹:
(1)初始化和賦值進行的轉換
在這裡插入圖片描述
(2)以{}方式初始化時進行轉換(C++11)
C++11將使用大括號的初始化稱為列表初始化(list-initialization),因為這種初始化常用於給複雜的資料型別提供值列表。它對型別轉換的要求更嚴格,具體來說,列表初始化不允許縮窄(narrowing),即變數的型別可能無法表示賦給它的值。
(3)表示式中的轉換
當同一個表示式中包含兩種不同的算術型別時,C++將執行兩種自動轉換:首先,一些型別在出現時便會自動轉換;其次,有些型別在與其他型別同時出現在表示式中時將被轉換。
(4)自動轉換
在計算表示式時,C++將bool、char、unsigned char、signed char和short值轉換為int。具體來說,true被轉換為1,false被轉換為0。這些轉換被稱為整型提升(integral promotion)。
編譯器通過校驗表來確定在算術表示式中執行的轉換,下面是C++11版本的校驗表,編譯器將依次查閱該列表:

  • 如果有一個運算元的型別是long double,則將另一個運算元轉換為long double。
  • 否則,如果有一個運算元的型別是double,則將另一個運算元轉換為double。
  • 否則,如果有一個運算元的型別是float,則將另一個運算元轉換為float。 否則,說明運算元都是整型,因此執行整型提升。
  • 在這種情況下,如果兩個運算元都是有符號或無符號的,且其中一個運算元的級別比另一個低,則轉換為級別高的型別。
  • 如果有一個運算元為有符號的,另一個運算元為無符號的,且無符號運算元的級別比有符號運算元高,則將有符號運算元轉換為無符號運算元所屬的型別。
  • 否則,如果有符號型別可表示無符號型別的所有可能取值,則將無符號運算元轉換為有符號操作所屬的型別。
  • 否則,將兩個運算元都轉換為有符號型別的無符號版本。

(5)傳遞引數時的轉換
傳遞引數時的型別轉換通常由C++函式原型控制,然而,也可以取消原型對引數傳遞的控制,儘管這樣做並不明智。這種情況下,C++對char和double型別(signed和unsigned)應用整型提升,將float引數提升為double。
(6)強制型別轉換
強制型別轉換的格式有兩種:

(typeName) value //converts value to typeName type
typeName (value) //converts value to typeName type

第一種格式來自C語言,第二種格式是純粹的C++,新格式的想法是,要讓強制型別轉換就像是函式呼叫。強制型別轉換不會修改變數本身,而是建立一個新的、執行型別的值,可以在表示式中使用這個值。

C++11中的auto宣告
C++11新增了一個工具,讓編譯器能夠根據初始值的型別推斷變數的型別。在初始化宣告中,如果使用了關鍵字auto,而不指定變數的型別,編譯器將把變數的型別設定成與初始值相同。
處理複雜型別,如標準模組庫(STL)中的型別時,自動型別推斷的優勢才能顯現出來。
對於C++98程式碼:

std::vector<double> scores;
std::vector<double>::iterator pv = scores.begin();

C++11允許將其重寫為下面這樣:

std::vector<double> scores;
auot pv = scores.begin();