第一節 <背景>
條款13中講到“資源取得的時機便是初始化時機”并由此引出“以對象管理資源”的概念。通常情況下使用std中的auto_ptr(智能指針)和tr1::shared_ptr(引數智能指針)作為管理資源的對象。
事實上,這種管理方法十分有效。但是,auto_ptr和tr1::shared_ptr隻能管理基于堆(heap-based)的資源,而非heap-based的資源卻往往不适合。
是以,有的時候你需要建立自己的資源管理類。本文介紹的内容是在你建立自己的資源管理類時應該注意的事項。
第二節 <正文>
我們知道在C API中處理Mutex的互斥對象,有lock何unlock兩個函數可用:
void lock(Mutex* pm); // 鎖定pm指向的互斥量
void unlock(Mutex* pm); // pm指向的互斥量解鎖
假設我們寫了Lock類來管理鎖。
class Mutex{
public:
Mutex():Count(0){}
public:
int Count;
};
void lock(Mutex* pm){pm->Count++;}
void unlock(Mutex* pm){pm->Count--;}
class Lock
{
public:
explicit Lock(Mutex* pm):mutexPtr(pm)
{lock(mutexPtr);} // 将mutexPtr指向的互斥變量加鎖
~Lock(){unlock(mutexPtr);} // 将mutexPtr指向的互斥變量解鎖
private :
Mutex * mutexPtr;
};
上面代碼滿足RAII(Resource Acquisition is Initialization)原則即,資源在擷取時既是初始化時,失去時既是清理時。
想象下面的場景時,程式的輸出結果是什麼。
1 Mutex m;
2 cout << "Mutex is " << m.Count << endl;
3 Lock m1(&m);
4 cout << "Mutex is " << m.Count << endl;
5 Lock m2(m1);
6 cout << "Mutex is " << m.Count << endl;
7 m1.~Lock();
8 cout << "Mutex is " << m.Count << endl;
輸出結果為:
Mutex is 0
Mutex is 1
Mutex is 1
Mutex is 0
這是為什麼呢?前兩個0和1輸出無可厚非,第三個的輸出為拿m1作為執行個體對象去指派給m2,操作對象為m1,不會直接影響m;第四個互斥量m的管理者m1被銷毀了,那麼m也就被解鎖了。
在上面的例子中,m的值不斷被變更,顯然,這種資源的管理的方式是不合理的。
可能的解決方法:
1.禁止複制。禁止複制的做法具體的可參照條款6的說明。
class UnCopyable {
public:
UnCopyable(){}
private:
UnCopyable(const UnCopyable& ths) {
}
};
class Lock:private UnCopyable {
...
}
2.使用引用計數智能指針:tr1::shared_ptr。
從條款13我們已經知道引用計數智能指針會跟蹤使用該資源的所有對象數,計數為0時,資源會被删除。注意,這裡删除互斥量m不是我們所期待的,我們期待是解鎖互斥量
幸運的是tr1::shared_ptr允許自定義所謂的“删除”動作,該動作是在計數為0時執行的。于是類Lock可以是下面的樣子。
class Lock
{
public:
explicit Lock(Mutex* pm):mutexPtr(pm,unlock)
{lock(mutexPtr.get());} // 将mutexPtr指向的互斥變量加鎖
private :
shared_ptr<Mutex> mutexPtr;
};
有沒有發覺貌似少了點東西?對,析構函數沒有了。因為share_ptr會幫你完成這一工作。
3.複制管理對象時也複制所管理的資源。
請回頭想一個問題:為什麼需要自己的資源管理類?那麼,可能的理由是當不需要某個資源時,資源能被正常釋放(删除,其他動作)。資源存在多個複件并不可怕,可怕的是複件在該銷毀的時候卻沒有銷毀。也就是,管理對象與所管理的資源要一一對應。為了保證這種對應關系,在複制管理對象時也複制所管理的資源。
4.轉移資源的管理權。
在某些特殊場合下,你可能希望資源隻被一個對象擁有,也就是管理對象在copying時要進行資源所有權的轉移。從條款13中講到的auto_ptr可以完美的實作這個需求。
■總結
1.複制管理對象時,請一并複制對象所管理的資源,資源的copy行為決定了管理對象的copy行為
2.普遍的RAII class的copy行為是抑制複制,使用引用計數
轉載于:https://www.cnblogs.com/hustcser/p/4103527.html