這裏我就直接貼代碼然後進行說明了。
拷貝型資源管理對象
對於普適性的資源,比如string、vector、array等資源,我們通常採用拷貝的方式進行資源的賦值操作
下面是這種資源管理對象的基本構造:
template<typename T>
class Data
{
private:
T* pointer;
public:
Data(const Data& d) :pointer(new T(*(d.pointer))) {};
Data() :pointer(NULL) {};
Data(T* p) :pointer(p)
{
};
~Data()
{
delete pointer;
}
T& operator*() { return *(this->pointer); }
Data& operator =(Data rhs)
{
delete pointer;
pointer = new T(*(rhs.pointer));
return *this;
}
};
然後我們測試一下:
void test()
{
Data<int> p1(new int(3));
Data<int>p2 = p1;
*p2 = 5;
cout << *p1 << " "<<*p2<<endl;//輸出 3 5
}
可以看到,當這種資源管理對象發生賦值的時候,就會產生新的資源副本,然後兩個對象的資源就此隔離沒有任何關係了。一個對象資源的改變不會影響另一個資源對象管理的資源
控制權轉移的資源管理對象
這種控制權交換的情況有很多,比如mutex的鎖等等臨界資源,也就是隻能被一個線程使用的資源,這樣的資源不能進行拷貝,只能進行支配權的轉移
大致構造如下:
template<typename T>
class Data
{
private:
T* pointer;
public:
Data(Data& d):pointer( d.pointer)
{
d.pointer = NULL;
};
Data() :pointer(NULL) {};
Data(T* p=NULL) :pointer(p)
{
};
~Data()
{
delete pointer;
}
T& operator*() { return *(this->pointer); }
Data& operator =(Data rhs)
{
delete pointer;
pointer = rhs.pointer;
rhs.pointer = NULL;
return *this;
}
};
當管理這種資源的對象進行賦值操作或則拷貝構造的時候,就會取消源資源對象對資源的的控制權,然後由新的資源管理對象對資源進行獨自的管理
只有一個本體(但能被多個對象訪問)的資源
還有一種資源,這種資源產生之後可以被大家共享。每個共享者實際上使用的都是同一個資源副本,當其中一個使用者被析構了不一定會釋放內存,而是所有使用者都被銷燬了,纔會釋放這塊資源佔據的內存。我們就添加一個計數器變量來統計使用者數量。
下面就是一個簡略的計數型資源管理對象的設計:
template<typename T>
class Data
{
private:
size_t* count;
T* pointer;
public:
Data(const Data& d) :pointer(d.pointer), count(d.count)
{
++(*count);
}
Data() :pointer(NULL),count(NULL) {};
Data(T* p = NULL) :pointer(p), count(new size_t(1)) {};
~Data()
{
cout << "~Data" << endl;
if (--(*count) == 0)
{
delete pointer;
delete count;
cout << "無人訪問,刪除共享資源" << endl;
}
}
T& operator*() { return *(this->pointer); }
size_t user() { return *count; };
Data& operator =(Data rhs)
{
pointer = rhs.pointer;
count = rhs.count;
*(this->count) += 1;
return *this;
}
};
由於在賦值和拷貝的時候要對這個資源的所有計數器都進行更新,所以使用了
size* count
(一個指針對象)來進行實時同步。並且提供user()
來查看當前有多少使用者。
一個測試代碼:
void test()
{
Data<int> p1(new int(3));
Data<int>p2 = p1;
*p2 = 5;
cout << *p1 << " " << *p2 << endl;
cout << "user: " << p1.user() << endl;
}
結果如下:
5 5
user: 2
~Data
~Data
無人訪問,刪除共享資源
可以看到,是很符合我們預期的,所有資源都可以很好的被分到不同的類別中去,然後進行不同類型資源的管理。保證資源的不同使用方法都能得到安全釋放。