c++11 新特性深入理解與應用 讀書筆記

2020-08-11 22:06:24
  • 目標問題
  1. 什麼是lambda,怎樣使用它是最好的?
  2. decltype和auto型別推導有什麼關係?
  3. 什麼是移動語意,以及(右值參照)是如何解決轉發問題的?
  4. default/deleted函數以及override是怎麼回事?
  5. 異常描述符被什麼替代了?noexcept是如何工作的?
  6. 什麼是原子型別以及新的記憶體模型?
  7. 如何在c++11中做並行程式設計?

1. 保持與C99相容

  1. 預定義宏
  2. _func_預定義操作符
  3. _Pragma操作符
  4. 不定參數宏定義以及_VA_ARGS_
  5. 寬窄字串連線(char wcahr_t)
  6. noexcept修飾符 與 noexcept操作符
  7. 快速初始化成員變數
  8. 非靜態成員的sizeof()
  9. 擴充套件的friend語法
  10. 10.final/override控制
  11. 模板函數的預設模板參數
  12. 外部模板(extern)
  13. 區域性和匿名型別作爲模板實參

2. 通用爲本,專用爲末

  1. 繼承建構函式
    https://www.runoob.com/w3cnote/cpp11-inheritance-constructor.html
    使用using宣告,來宣告基礎類別的所有建構函式
  2. 委派建構函式
  3. 右值參照:移動語意和完美轉發
    3.1 指針成員與拷貝構造
    對c++程式設計師來說,編寫c++程式有一條必須注意的規則,就是類中包含指針成員的話,就要特別小心拷貝建構函式的編寫。因爲一個不小心,就會出現記憶體漏失。
    在未宣告建構函式的情況下,c++會爲類生成一個淺拷貝的建構函式。如果類中包含指針,最佳解決方案事使用者自定義拷貝建構函式來實現「深拷貝」,避免懸掛指針的困擾。
    3.2 移動語意
    3.3 左值、右值和右值參照
    a=b+c; 在這個賦值表達式中,a就是一個左值,而b+c則是一個右值。這種識別左值、右值的方法仍然有效。不過在c++中還有一個被廣泛認同的說法,那就是可以取地址、有名字的就是左值,反之,不能取地址、沒有名字的就是右值。。那麼。在這個加法賦值表達式中,&a是允許的操作,而&(b+c)則不會通過編譯,因此,a是一個左值,(b+c)是一個右值。
    c++11將右值分爲將亡值(xvalue),另一個是純右值(prvalue,Pure Rvalue)
    純右值就是c++中的標準右值,講的是用於辨識臨時變數和一些不跟物件關聯的值;將亡值則是c++ 新增的跟右值參照相關的表達式,這樣表達式通常是將要被移動的物件(移爲他用)
  • 3.4 顯示轉換操作符
  • 3.5 列表初始化
    3.5.1 初始化列表
    在c++98中,允許使用花括號{}對陣列元素進行統一的集合(列表)初始值設定。比如:
int arr[5] = {0};
int arr[] = {1223}

這些都是合法的表達式。不過一些自定義型別,卻無法享受這樣的便利初始化。通常,如標準程式庫中的vector,總是需要宣告物件–回圈初始化這樣重複的動作,這對於使用模板的泛型程式設計無疑是不利的。
3.5.2 防止型別收窄
使用列表初始化的一個最大優勢是可以防止型別收窄。型別收窄一般是指一些可以使得數據變化或者精度丟失的隱形型別轉換。

  • 3.6 POD型別
  • 3.7 非受限聯合體
  • 3.8 使用者自定義字面量
    在c++程式中,程式設計師常常會使用結構體或者類來創造新的型別,以滿足實際的需求。
  • 3.9 內聯命名空間

5. 提高型別安全

5.1 強型別列舉

5.2 記憶體管理:智慧指針與垃圾回收

  • 5.2.1 顯式記憶體管理
    C++程式的典型症狀:程式執行時突然退出,佔用的記憶體越來越多等等,這些其實都可以追溯到顯式記憶體管理上。通常情況下,這些症狀都是由於程式沒有正確處理堆記憶體的分配與釋放造成的,從語言層面來講,我們可以歸納爲以下一些問題:
    1. 野指針:一些記憶體單元已被釋放,之前指向它的指針卻還在被使用。這些記憶體有可能被執行時系統重新分配給程式使用,從而導致了無法預測的錯誤。
    2. 重複釋放:程式試圖去釋放已經被釋放過的記憶體單元,或者已經被重新分配過的記憶體單元,就會導致重新釋放錯誤。通常重複釋放記憶體會導致C/C++執行時系統列印出大量錯誤及診斷資訊。
    3. 記憶體漏失:不再需要使用的記憶體單元如果沒有被釋放就會導致記憶體漏失。如果程式不斷地重複進行這類操作,將會導致記憶體佔用劇增。
      在C++11新標準中,智慧指針被進行了改進,以更加適應實際地記憶體需求。
  • 5.2.2 C++11的智慧指針
    c++11標準中改用unique_ptr、shared_ptr及weak_ptr等智慧指針來自動回收堆分配的物件。
    從實現上來講,unique_ptr是一個刪除了拷貝建構函式、保留了移動建構函式的指針封裝型別。
    shared_ptr同樣形如起名,允許多個該智慧指針共用地"擁有"同一堆分配物件地記憶體。與unique_ptr不同的是,由於在實現上採用了參照計數,所以一旦一個shared_ptr指針放棄了」所有權「,其他的shared_ptr對物件記憶體的參照並不會受影響。只有在參照計數歸零的時候,shared_ptr纔會真正釋放所佔有的堆記憶體的空間。
    c++11中的智慧指針還包含了weak_ptr這個類別範本。weak_ptr的使用更復雜以下,它可以指向shared_ptr指針指向的物件記憶體,卻並不擁有該記憶體而使用weak_ptr成員lock,則可以返回其指向記憶體的一個shared_ptr物件,且在所指物件記憶體已無效時,返回指針空值(nullptr),這在驗證shared_ptr智慧指針的有效性上會很有作用。
  • 5.2.3 垃圾回收的分類
    垃圾回收的方式雖然很多,但主要分爲兩大類:
  1. 基於參照計數的垃圾回收器
    簡單的說,參照計數主要時=是使用系統記錄物件被參照(參照、指針)的次數。當物件被參照的次數變爲0時,該物件即可被視作」垃圾「而回收。
  2. 基於跟蹤處理的垃圾回收器
    相比於應用計數,跟蹤處理的垃圾回收機制 機製更被廣泛的應用。其基本方法是產生跟蹤物件的關係圖,然後進行垃圾回收。