Effective C++ 筆記 part 3、4

13.以對象管理資源

  1. 資源包括:內存、文件描述符、互斥鎖、圖形界面中的字型和筆刷、數據庫連接、網絡sockets 當不再使用資源時,一定要把它歸還給系統

以對象管理資源(資源取得時機便是初始化時機RAII :Resource Acquisition Is Initialization):把資源放進對象內,便可依賴c++的析構函數自動調用機制確保資源被釋放

    1. 獲得資源後理解放進管理對象中
    2. 管理對象運用析構函數確保資源被釋放
  1. auto_ptr被銷燬時會自動刪除它所指之物,所以一定要注意別讓多個auto_ptr指針指向同一對象(否則對象會被刪除一次以上,行爲未定義)

auto_ptr指針:若通過copy構造函數或者copy assignment操作符複製它,它會變成null,而複製所得的指針將取得資源唯一擁有權,STL容器不能用auto_ptr

  1. shared_ptr是一個RSCPs(引用計數型智慧指針,無法打破環狀引用,例如兩個沒使用的對象彼此互指,好像對象還處在被使用狀態),shared_ptr的copy行爲比較直觀

14.在資源管理類中小心copying行爲

複製RAII對象必須一併複製它所管理的資源,所以資源的copying行爲決定RAII對象的copying

普遍而常見的 RAII class copying行爲是:抑制copying、施行引用計數法

15.在資源管理類中提供對原始資源的訪問

  1. APIs往往要求訪問原始資源,所以沒一個RAII  class應該提供一個“取得其所管理之資源”的辦法
  2. 對原始資源的訪問可能經由顯式轉換或隱式轉換。一般而言顯示轉換比較安全

16.成對使用new 和delete 時要採取相同形式

  1. 使用new:內存被分配出來 –> 針對此內存會有一個(或更多)構造函數被調用

使用delete:針對此內存一個(或更多)析構函數被調用->釋放內存

  1. delete xxx; // 認爲指針指向單一對象

delete[] xxx;//認爲指針指向一個數組

17.以獨立語句將newed對象置入智能指針

  1. 以獨立語句將newed對象存入智能指針內(先創建對象,將它置入一個智能指針內,然後再把智能指針傳給函數調用。)。如果不這樣做,一旦異常被拋出(比如在new對象和執行shared_ptr構造函數之間的某一步異常),有可能導致難以察覺的資源泄露。
  2. shared_ptr構造函數需要一個原始指針,該構造函數是個explicit構造函數。

18.讓接口容易被使用,不易被誤用

  1. 促進正確使用:接口的一致性,與內置類型的行爲兼容
  2. 阻止誤用:建立新類型,限制類型上的操作,束縛對象值,消除客戶的資源管理責任
  3. shared_ptr支持定製型刪除器,可防範DLL問題(cross-DLL problem:對象在一個DLL中被創建,在另一個DLL中被銷燬),可被用來自動解除互斥鎖等

19.設計class猶如設計type

考慮以下問題:

對象創建、銷燬、初始化、賦值(考慮初始化和賦值的差別)、值傳遞(新type的對象如果以值傳遞,會發生什麼)、合法值、繼承關係(是否需要配合某個繼承圖系)、轉換(新type與其他type之間是否需要轉換及需要什麼轉換)、一般化、操作符、函數(需要暴露及需要private的)

20. 寧以 pass-by-reference-to-const(高效) 替換 pass-by-value(有拷貝操作)

(前者通常更高效、避免切割問題(slicing problem),但不適用於內置類型、STL迭代器、函數對象)

  1. 切割問題:當一個derived class對象以by value方式傳遞並被視爲一個base class對象,base class的copy構造函數會被調用,而“造成此對象的行爲像個derived class對象”的那些特化性質全被切割掉了,僅僅留下一個base class對象
  2. pass-by-reference-to-const不適用於STL及內置類型

21.必須返回對象時,不返回其reference

  1. 棧對象:函數內的對象(local對象)在函數退出前被銷燬了,如果返回某個local對象的reference會引發未定義行爲。

絕不要返回pointer或reference指向一個local stack對象,或返回reference指向一個heap-allocated對象,貨返回pointer或reference指向一個local static對象而有可能同時需要多個這樣的對象

22.將成員變量聲明爲private

  1. 將成員變量聲明爲private,這可賦予客戶訪問數據的一致性,可細微劃分訪問控制、允許約束條件獲得保證,並提供class作者以充分的實現彈性
  2. protected並不比public更具封裝性

23.寧以non-member、non-friend替換member函數

  1. namespace和class不同,前者可以跨越多個源碼文件而後者不可以
  2. 以non-member、non-friend替換member函數,可以增加封裝性、包裹彈性和機能擴充性

24.若所有參數皆需類型轉換,請爲此採用non-member函數

如果需要爲某個函數的所有參數(包括this指針所指的那個隱喻參數)進行類型轉換,那麼這個函數必須是non-member(否則可能會因爲找不到參數匹配的函數而調用失敗)

25.考慮寫出一個不拋出異常的swap函數

  1. 當std::swap對你的類型效率不高時,提供一個swap函數,並確定和這個函數不拋出異常。
  2. 如果你提供一個member swap,也該提供一個non-swap用來調用前者。對於class(而非templates),也要特化swap。
  3. 調用swap時應針對std::swap使用using聲明式,然後調用swap並且不帶任何“命名空間資格修飾”。
  4. 爲“用戶特定類型”進行std templates全特化是好的,但千萬不要嘗試在std內加入某些對std而言全新的東西。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章