天天看點

C++ Primer 0x02 學習筆記

📔 C++ Primer 0x02 學習筆記

第 2 章 變量和基本類型

2.1 基本内置類型

2.1.1 算術類型

  • 基本内置類型:算術類型和空類型
  • 算術類型:字元、整型數、布爾值、浮點數
  • 除了布爾型和擴充字元型,其他整形可以劃分為有符号類型和無符号類型
  • char類型可能帶符号,可能不帶符号
  • 無符号類型所有比特位用來存值,有符号類型沒有規定怎麼存,但應當平衡
  • 浮點一般選double,精度比float高,運算代價比long double少,成本效益最好

2.1.2 類型轉換

  • 整數類型給浮點類型,小數部分為0,如果整數空間超過浮點類型容量,可能會有精度損失
  • 無符号類型表示超範圍的數自動取模,模空間大小
  • 帶符号類型表示超範圍數,結果為定義
  • 不要混用有符号類型和無符号類型,有符号類型會轉成無符号類型

2.1.3 字面值常量

  • 整型字面值,0開頭為八進制,0x開頭為十六進制
  • 十進制整形字面值預設是帶符号數,類型是能容納其大小的最小的類型,short沒有對應字面值
  • 負号實際不在字面值裡
  • 浮點數字面值表現為一個小數或科學計數法,預設double類型
  • 單引号是字元字面值,雙引号是字元串字面值
  • 如果兩個字元串字面值位置緊鄰且中間隻有換行符、空格、縮進,那麼他們是整體
  • 字元串字面值實際上是常量字元構成的數字,末尾會加上空字元(’\0’)
  • 兩類字元不能直接列印:不可列印字元、轉移序列
  • 可以通過前字尾指定字面值類型,長整型一般用L防止l和1混淆
  • 布爾型字面值 true、false,指針型字面值 nullptr
  • long long c++11

2.2 變量

2.2.1 變量定義

  • 變量的基本形式:類型說明符 + 變量名
  • 初始化不是指派,初始化的含義是建立變量時賦予一個新值,而指派的含義是把對象目前的值擦除,用一個新的值代替
  • 清單初始化用{},如果存在丢失資訊的危險,編譯器會拒絕初始化請求
  • 定義變量沒有給初始值,那麼就會被預設初始化,初始化的值取決于變量類型
  • 内置變量類型如果在函數内部則不被初始化,他的值未定義;如果在所有函數外部,那麼初始化為0

2.2.2 變量聲明和定義的關系

  • C++支援分離式編譯
  • 聲明使得名字為程式所知,定義負責建立與名字相關聯的實體
  • 如果要聲明一個變量而不是定義,那就加上extern并且不要顯式地初始化
  • 任何包含顯式初始化的聲明會變成定義
  • 函數内部初始化一個extern會報錯
  • 變量隻能被定義一次,但可以聲明多次
  • C++是一種靜态類型語言,編譯過程中會進行類型檢查

2.2.3 辨別符

  • C++ 辨別符 (identifier) 由字母、數字、下劃線組成,必須以字母或下劃線開頭,大小寫敏感
  • 關鍵字保留字不能作為辨別符
  • 變量命名規範
  • 辨別符展現具體含義
  • 變量名一般小寫
  • 自定義類名一般大寫字母開頭
  • 如果辨別符由多個單詞組成,單詞之間應該有明顯區分

2.2.4 名字的作用域

  • 作用域,一般用花括号分割
  • 全局作用域
  • 塊作用域
  • 嵌套作用域:内層作用域,外層所用域,注意覆寫問題

2.3 複合類型

2.3.1 引用

  • 引用 (reference) 給對象起了另一個名字,但他不是對象
  • 定義引用的時候必須初始化,并且引用和初始值綁定 (bind) 在一起,而不是拷貝給引用
  • 無法令引用重新綁定到另一個對象
  • 引用不是一個對象,無法定義引用的引用
  • 定義多個引用的時候每個引用辨別符都要以&開頭
  • 引用類型必須和對象類型嚴格比對,不能和字面值或某個表達式的計算結果綁定(常量引用除外,見2.4節 const 限定符)
  • 引用能幹什麼取決于綁定的對象能幹什麼

2.3.2 指針

  • 指針本身是對象,允許對指針指派和拷貝,可以先後指向幾個不同的對象
  • 指針無需在定義時指派,如果沒有初始化那就是個不确定的值
  • 定義多個指針,每個前面都要以*開頭
  • 指針存放某個對象的位址,要想擷取位址就要使用取位址符&
  • 指針類型要和指針對象嚴格比對(有兩個特例)
  • 指針值應該屬于下面四種狀态之一
  • 指向一個對象
  • 指向緊鄰對象所占空間的下一個位置
  • 空指針
  • nullptr
  • 0,要字面常量,不能是等于0的變量
  • NULL 在cstdlib中被定義為0 (預處理變量不屬于命名空間,直接用)
  • 無效指針
  • 利用解引用符* 通路對象,解引用操作隻适合指向了某個對象的有效指針
  • 指針相等3種可能
  • 都為空
  • 指向同一個對象
  • 指向同一個對象的下一位址
  • void* 指針
  • 可以存放任意對象的位址
  • 不能直接操作void* 指針所指的對象
  • 可以和其他函數作比較,賦給另一個 void* 指針,作為函數的輸入輸出
  • void* 視角看記憶體空間也就隻是記憶體空間,沒法通路記憶體空間中所存的對象

2.3.3 了解複合類型的聲明

  • 變量的定義:基本資料類型+一組聲明符,類型修飾符如:指針、引用等隻是聲明符的一部分罷了
  • 指向指針的指針要兩次解引用
  • 引用本身不是對象,是以沒有指向引用的指針;但是指針有對象,存在指向指針的引用
  • 面對一條比較複雜的指針或引用的聲明語句時,從右向左閱讀有助于弄清含義,離變量名最近的符号對變量名有着最直接的影響。

2.4 const 限定符

  • const 對象一旦建立後值不能改變, const 對象必須初始化
  • cons t對象被其他對象初始化,它們是不是 const 沒關系。牢記初始化和指派的差別,指派是擦除舊值,賦予新值,有改變值的含義。
  • 預設狀态下,const 對象隻在檔案内有效,是以如果要多檔案共享就要在 const 前加 extern

2.4.1 const的引用

  • 引用綁定到 const 對象上稱為對常量的引用 (reference to const),常量引用隻是它的簡稱。實際上不存在常量引用,因為引用不是對象,不能用 const 讓它的值不變
  • 對常量的引用不能被用作修改它綁定的對象
  • 不能用一個非常量引用指向一個常量對象
  • 初始化常量引用的時候允許用任意表達式作為初始值,隻要能轉換成引用的類型即可(中間會産生一個臨時量)
  • const 的引用可能引用一個非 const 的對象,這樣的話隻是限定了通過引用改變對象的值,但是可以通過其他途徑去改變

2.4.2 指針和 const

  • 區分指向常量的指針 (pointer to const) 和 const 指針 (const pointer)
  • 指向常量的指針不能用于改變其所指對象的值,存放常量位址的值隻能用指向常量的指針
  • 指向常量的指針可以指向非常量
  • const 指針 必須初始化

2.4.3 頂層const

  • 頂層 const 表示 指針本身是個常量,底層 const 表示 指針指向的對象是常量
  • 當執行對象的拷貝操作的時候,兩個對象必須有相同的底層 const 資格,或者兩個對象的資料類型可以互相轉換,一般來說非常量可以轉為常量,反之不可以
  • 常量表達式在編譯過程中就能得到計算結果,用常量表達式初始化的 const 對象 也是常量表達式
  • 如果認定變量是一個常量表達式,那就把他聲明成 constexper,這樣編譯器會去嚴重變量的值是否是一個常量表達式

2.4.4 constexpr 和 常量表達式

  • 字面值類型:算術類型、引用、指針
  • constexper 指針的初始值必須是 nullptr 或 0,或是存在某個固定位址中的對象(函數體内無固定位址,所有函數外固定)
  • constexper 聲明中定義了指針,你們那麼 constexper 隻對指針有效,與指針所指對象無關
  • constexpr 指針既可以指向常量也可指向非常量

2.5 處理類型

2.5.1 類型别名

  • 關鍵字 typedef 和 using 别名聲明
  • 如果類型别名指代複合類型,要謹慎寫,不要直接當作define去替換,要把别名當作一個整體來看待

2.5.2 auto 類型說明符

  • auto 讓編譯器通過初始值來推斷類型,是以 auto 定義的變量必須有初始值
  • 使用 auto 在一條語句裡聲明多個變量,他們的基本類型(&和*隻是聲明符的一部分,而不屬于基本類型)要相同。
  • 當引用被作為初始值的時候,編譯器以引用對象的類型作為 auto 的類型,如果要推斷為引用的話需要明确指出
  • auto 一般會忽略 頂層 const,如果不想忽略那麼要明确指出

2.5.3 decltype 類型訓示符

  • decltype 選擇并傳回操作數的資料類型
  • 如果 decltype 使用的表達式是一個變量,那麼傳回變量類型(包括頂層const和引用)
  • 如果 decltype 使用的表達式不是變量,那麼傳回表達式結果的類型
  • 引用和對象是同義詞,不過在 decltype 這我們特殊區分
  • 如果 decltype 使用的表達式是解引用操作,那麼傳回得到引用類型
  • 對于 decltype 而言,變量加不加括号是不一樣的,decltype((variable)) 傳回永遠是引用,decltype(variable) 隻有當variable 本身是引用的時候才傳回引用

2.6 自定義資料類型

  • 類内部定義的名字必須唯一,但是可以與類外部定義的名字重複
  • 類體右側表示結束的花括号必須寫一個分号,因為類體後面可以緊跟變量名
  • 每個對象有自己的一份資料成員的拷貝,修改一個對象的資料成員不會影響其他對象
  • 頭檔案一旦改變,相關的源檔案必須重新編譯擷取更效過的聲明
  • 類通常被定義在頭檔案當中,而且類所在頭檔案名字應該與類名字一樣
  • 確定多檔案多次包含仍能安全工作的技術是預
  • 預處理器(preprocessor),由C語言繼承過來
  • C++ 還經常用到頭檔案保護符(header guard)
  • 預處理變量無視C++中關于作用域的規則