在C++中,智能指針是存儲一些動態分配對象或者資源的類,主要用於控制資源或者動態對象的使用生存期,設計的目的如下:
保證能夠正確的分配和銷毀動態對象或者資源,以防止內存洩露等問題。
跟蹤對象或者資源的使用情況。
智能指針的實現一般都是使用引用計數,將一個計數器與使用的指針相關聯起來,此時引用計數器跟蹤該所屬類有外部多少共享。因此在實現的時候,就有兩個根本的部分
計數表示。用於實現對動態對象或者資源使用的計數。
指針表示。用於將動態對象或者資源的指針使用間接表現。
根據智能指針主要是上面兩大部分,智能指針可以稱為“智能計數指針”,智能主要是計數的意思,當然計數的用途就因應用而不同了,或者只是為了跟蹤,或者是為了資源管理,或者是為了防止多次釋放等等。
一,智能指針實現
下面的模板類,用於實現對指針的封裝,其實現的功能如下:
指針構造。根據需要被封裝的動態對象或者資源的指針,構造智能指針,一般在構造時,會將資源的計數加1;
指針運算符重載。下面重載了*,=,->等運算符。
指針數據。一個指向模板類型的指針,T* ptr_
[cpp]
template <class T>
class scoped_refptr {
public:
scoped_refptr() : ptr_(NULL) {
}
scoped_refptr(T* p) : ptr_(p) {
if (ptr_)
ptr_->AddRef();
}
scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) {
if (ptr_)
ptr_->AddRef();
}
template <typename U>
scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) {
if (ptr_)
ptr_->AddRef();
}
~scoped_refptr() {
if (ptr_)
ptr_->Release();
}
T* get() const { return ptr_; }
operator T*() const { return ptr_; }
T* operator->() const { return ptr_; }
T* release() {
T* retVal = ptr_;
ptr_ = NULL;
return retVal;
}
scoped_refptr<T>& operator=(T* p) {
// AddRef first so that self assignment should work
if (p)
p->AddRef();
if (ptr_ )
ptr_ ->Release();
ptr_ = p;
return *this;
}
scoped_refptr<T>& operator=(const scoped_refptr<T>& r) {
return *this = r.ptr_;
}
template <typename U>
scoped_refptr<T>& operator=(const scoped_refptr<U>& r) {
return *this = r.get();
}
void swap(T** pp) {
T* p = ptr_;
ptr_ = *pp;
*pp = p;
}
void swap(scoped_refptr<T>& r) {
swap(&r.ptr_);
}
protected:
T* ptr_;
};
有了這個類之後,我們可以定義一個指針,如針對class window的智能指針
[cpp]
scoped_refptr<window> win;
此時,上面的模板就會包含一個window *ptr_的指針,從上面可以看出,為了能夠正常工作,這類型的指針都必須要實現AddRef和Release方法,這應該不會是要求在class window中實現的吧?那也不太不符合封裝的正常邏輯了。答案是:當然不會在class window中實現,這兩個方法主要是針對計數的方法,專門針對class window封裝一個計數器類,下面的計數器封裝
二,計數器的封裝
這個類很簡單,有三個地方需要注意
類從模板類型繼承,就是從T繼承。上面的class window的話,就是RefCountedObject是window的派生類。
封裝計數器ref_count_。需要注意的是,對計數器的加減操作應該盡可能的保持原子性。
計數器類提供多個構造函數,都是對傳入的類型T的多種構造支持。
[cpp]
template <class T>
class RefCountedObject : public T {
public:
RefCountedObject() : ref_count_(0) {
}
template<typename P>
explicit RefCountedObject(P p) : T(p), ref_count_(0) {
}
template<typename P1, typename P2>
RefCountedObject(P1 p1, P2 p2) : T(p1, p2), ref_count_(0) {
}
template<typename P1, typename P2, typename P3>
RefCountedObject(P1 p1, P2 p2, P3 p3) : T(p1, p2, p3), ref_count_(0) {
}
template<typename P1, typename P2, typename P3, typename P4>
RefCountedObject(P1 p1, P2 p2, P3 p3, P4 p4)
: T(p1, p2, p3, p4), ref_count_(0) {
}
template<typename P1, typename P2, typename P3, typename P4, typename P5>
RefCountedObject(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
: T(p1, p2, p3, p4, p5), ref_count_(0) {
}
virtual ~RefCountedObject() {
}
virtual int AddRef() {
return Increment(&ref_count_);
}
virtual int Release() {
int count = Decrement(&ref_count_);
if (!count) {
delete this;
}
return count;
}
protected:
int ref_count_;
};
三,實例
[cpp]
scoped_refptr<Window> win(new RefCountedObject<Window>(&client, &wnd));
上面的實例定義了一個智能指針win,式中client和wnd為其它參數,與定義無關。