【筆記】C++中的智能指針

參考自《effective morden c++》

裸指針的缺點

  1. 無法知道指向的是單個對象還是一個數組.
  2. 無法知道使用完之後是否需要析構,即是否擁有指向的對象.
  3. 無法知道應當如何析構(使用 delete 還是專門的函數)
  4. 無法知道單個析構還是數組析構.
  5. 不能保證只析構一次。少了會導致內存泄漏,多了是UB.
  6. 無法檢查指針空懸.

std::unique_ptr

  1. 足夠小、足夠快,幾乎和裸指針相同.
  2. 是一個只移類型(不可複製),當其析構時,內部的對象也會被析構。
  3. 可以自定義刪除器,會略微增大尺寸.
  4. 自定義刪除器的類型需要加入到模板參數中
  5. 不建議用其存儲數組,可以使用 vector, array 等.
  6. 可以方便地轉爲 shared_ptr.

std::shared_ptr

  1. 尺寸是裸指針的兩倍,因爲內部既包含一個資源指針,又包含一個控制塊的指針.
  2. 引用計數是原子性的.
  3. 自定義刪除器不需要加入到模板參數.
  4. 控制塊包括:引用計數、弱計數、其他數據(自定義刪除器等)
  5. 不要用保存好的裸指針來創建 shared_ptr,直接從 new 創建。因爲會創建一個新控制塊.
  6. 由上,從 this 創建指針也是很危險的,可以讓類 T 繼承 std::enable_shared_from_this<T>,然後使用 shared_from_this 函數創建.
    這裏的設計模式叫 奇異遞歸模板模式.
  7. 不要用它保存數組

std::wake_ptr

  1. 用於 sp 的輔助,不能直接獲取指向的資源.
  2. expired() 判斷是否失效.
  3. 如果需要線程安全地判斷是否失效並且沒失效時返回一個 shared_ptr,可以使用
    • lock(),如果失效返回的 sp 爲空
    • 直接創建,如果失效會返回異常.
  4. 用途:緩存觀察是否失效,觀察者模式,避免 sp 循環依賴.
  5. 控制塊裏的弱計數記錄 wp 的數量,當 sp 和 wp 數量全部爲0後,控制塊纔會被析構。

std::make_unique, std::make_shared

  1. make_unique 是 C++ 14的部分,可以自己寫一個(暫略)
  2. 優先使用 make_shared,因爲速度更快:控制塊和託管對象處在同一內存區域。
  3. 不適用的情況包括:自定義刪除器,直接傳遞大括號初始化。
  4. 使用 make_shared 後,如果 sp 數量已經爲0,但還有 wp,那麼內存不會被釋放(對象已經被析構,控制塊未被析構).
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章