程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> Effective C++筆記:資源管理

Effective C++筆記:資源管理

編輯:C++入門知識

資源:動態分配的內存、文件描述器、互斥鎖、圖形界面中的字型與筆刷、數據庫連接以及網絡sockets等,無論哪一種資源,重要的是,當你不再使用它時,必須將它還給系統。

條款13:以對象管理資源

當我們向系統申請資源後,一定要記得釋放,不然就容易發生內存洩漏。但是意識到這樣一件事並不是很容易,比如我們是通過一個函數來動態分配內存並返回一個指針。

Investment* ceateInvestment();// 返回指針,指向動態分配對象
void f()
{
    Investment* pInv = ceateInvestment();
    // ...
    delete pInv;
}

即使像上面的代碼一樣,我們在用完指針pInv後,我們調用了delete,但是還是可能出問題,有時候我們可能在...的部分提前return或跳出了循環,甚至在該部分發生了異常,這都導致delete根本執行不到。

解決方法是我們把指針放在一個資源管理的類裡,讓類對象在生命結束的時候,會自動調用析構函數,而析構函數裡會執行delete。

兩個常被使用的RAII類分別是:shared_ptr和unique_ptr,它們間不同的是shared_ptr允許存在同一內存區域的多個指針拷貝,而unique_ptr只允許一份指針指向對象,當uniuqe_ptr發生賦值操作時,用於賦值的指針將會變成null。

條款14:在資源管理類中小心copying行為

在實際管理資源時,並非所有的資源都是堆內存(heap),所以unique_ptr或shared_ptr這樣的智能指針往往不適合作為資源管理者。

比如你需要控制類型為Mtux的互斥器對象,共有lock和unlock兩函數可用,你需要保證的就是不要忘記將一個被鎖住的Mutex解鎖,我們的想法的主旨就是:資源在構造期間創建,在析構期間釋放。

class Lock
{
public:
    explicit Lock(Mutex* pm) :mutexPtr(pm){ lock(mutexPtr;) }// 獲得資源
    ~Lock(){ unlock(mutexPtr); }// 釋放資源 
};

這樣雖然很好,但是如果Lock被復制了,就會發生問題。它可能會引起對了一Mutex解鎖兩次。

常見的解決方案有2種:一種是禁止復制;第二種是對底層資源祭出“引用計數法”,這也是shared_ptr實現原理。

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

很多API接口往往要求訪問原始資源,所以每一個RAII class應該提供一個“取得其所管理之資源”的辦法,比如提供一個get函數。

對原始資源的訪問可能經由顯式轉換或隱式轉換。一般而言顯式轉換比較安全,但隱式轉換對客戶比較方便。

條款16:成對使用new和delete時要采用相同形式

如果你在new表達式中使用[],必須在相應的delete表達式中使用[]。如果你在new表達式中不使用[],一定不要在相應的delete表達式中使用[]。

string* stringPtr1 = new string;
string* stringPtr2 = new string[100];
delete stringPtr1;        // 刪除一個對象
delete[] stringPtr2;    // 刪除一個由對象組成的數組

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

假設我們有個函數用來控制程序的優先權,另一個函數用來在某個動態分配所得到的Wieget上進行某些帶有優先權的處理:

int priority();
void processWidget(shared_ptr<Widget>pw, int priority);

現在假如我們這樣調用它:

processWidget(share_ptr<Widget>(new Widget),priotrity());

在調用processWidget之前,編譯器必須創建代碼,做以下三件事:

  • 調用priority
  • 執行”new Widget”
  • 調用shared_ptr構造函數

C++編譯器並不保證上次代碼執行的次序,但有一點可以保證,那就是new Widget肯定發生成share_ptr構造函數之前。

假如priority發生在第二步,並且執行過程中發生了異常,那就有可能資源不能正常的釋放。

避免這種情況,就需要使用分離語句,先創建Widget,然後再將它置入一個智能指針內,然後再把那個智能指針傳給processWidget。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved