關於shared_ptr

   首先了解shared_ptr毫無疑問的是智能指針的一種,智能指針是爲了解決在大型代碼裏無法不好控制指針的問題,例如:在類裏面如果出現了動態開闢出來的空間,有一個指針指向這塊空間,如果在相應的作用範圍之內沒有將其delete掉會造成內存的泄漏,所以這樣就必須手動的對這一塊空間進行釋放,但是這非常不利於我們的工作,所以我們就引入了智能指針,它是一個類,它的作用範圍結束就自動釋放了,所以這樣達到了智能的管理這一塊空間。所以shared_ptr也自然地擁有了上面的特性和功能,現在就對shared_ptr做一個較爲深層次的理解並掌握它的使用。

   Boost庫的智能指針(ps:新的C++11標準中已經引入了unique_ptr/shared_ptr/weak_ptr),所以言下之意就是在使用unique_ptr/shared_ptr/weak_ptr之前都需要進行boost編譯,所以這樣也不方便使用,在c++11中將boost也納入了標準,這樣就可以在較高版本的編譯器下直接使用這些智能指針。所以shared_ptr可以在我的編譯器下直接使用而不需要編譯,因爲我的編譯器是13版的。

   SharedPtr,利用字符串相似的寫時拷貝方式實現,讓創建的對象維護同一塊空間,並且用一個int* _pcount對引用這塊空間的次數進行計數。


現在先對shared_ptr進行一個模擬的實現:

template <typename T>

class SharedPtr //相似於string類的寫實拷貝,如果用深拷貝的方式達不到指針的效果,p1=p2,不能讓p1和p2同時管理一塊空間

{

public:

                SharedPtr( T* ptr )

                                :_pcount( new int (1))

                                , _ptr( ptr)

                {


                }

                ~SharedPtr()

                {

                                 if (--(*_pcount) == 0)

                                {

                                                 delete _ptr;

                                                 delete _pcount;

                                }

                }

                SharedPtr( const SharedPtr & s)

                                :_ptr( s._ptr)

                                , _pcount( s._pcount)

                {

                                ++(*_pcount);

                }

/* 這種寫法較爲複雜

SharedPtr& operator=(const SharedPtr& s)//分三種情況,自己給自己賦值,兩對象指向同一空間,指向不同的空間

{

                if (_ptr != s._ptr)

                {

                                if (--(*_pcount) == 0)

                                {

                                                delete _ptr;

                                                delete _pcount;

                                }

                                _ptr = s._ptr;

                                _pcount = s._pcount;

                                ++(*_pcount);

                }

                return *this;

}

*/

SharedPtr& operator=( const SharedPtr s )//這種寫法較爲簡單,並且這樣寫法一致性好,在自賦值,指向同一塊空間賦值,指向不同空間的賦值都滿足

{

                swap(_ptr, s._ptr);

                swap(_pcount, s._pcount);

                 return *this ;

}

                 T& operator*()

                {

                                 return *_ptr;

                }

                 T* operator->()

                {

                                 return _ptr;

                }

protected:

                 T* _ptr;

                 int* _pcount;

};

上面是實現了shared_ptr的幾個基本函數,shared_ptr無疑的要實現成模板類,因爲它在運用時可以是不同類型的指針,同時它還要盡力的模仿的和原生指針比較相似。

/*****************************************************************/

   上面是對shared_ptr的原理進行了分析,現在對shared_ptr在使用時要注意的問題進行分析(首先要了解shared_ptr在使用時會發生循環引用和定製刪除器這兩個要點)

  1. 循環引用問題

  shared_ptr的循環引用問題及其解決方法:(形成循環引用的原因是因爲cur最後釋放會依賴於next->_prev的釋放,而next的釋放又依賴於cur->_next的釋放,所以形成無法釋放的局面)


wKiom1cB43WC884mAAAjULCF-fE240.png

weak_ptr不完全增加引用計數,打破shared_ptr的死穴


2.定製刪除器:

  定置刪除器:在使用share_ptr時,因爲shared_ptr只能管理用new開闢出來的空間,因爲shared_ptr析構函數的實現是依靠delete _ptr實現,所以對於malloc和fopen等操作並不能做到析構,如果不定置刪除器將會導致程序的崩潰,因爲malloc需要用free來解決,fopen需要用fclose來解決(利用仿函數這個方法來實現定置刪除器)利用仿函數來解決問題,仿函數是一個類,對象可以像一個函數一樣調用,它是一個空類。

  下面實現定製刪除器的使用:


template <typename T,typename Del>

class SharedPtr

{

public:

void Release()

{

if (--(*_pcount) == 0)

{

_del(_ptr);

delete _pcount;

}

}

SharedPtr(T* ptr)

:_ptr(ptr)

, _pcount(new int(1))

{

}

~SharedPtr()

{

Release();

}

private:

T* _ptr;

int* _pcount;

Del _del; 

};

template <typename T>//定製刪除器(new)

struct Del//是個類,可以當作一個模板參數

{

void operator()(T* _ptr)

{

cout << "delete _ptr" << endl;

delete _ptr;

}

};


template <typename T>//定製刪除器(malloc)

struct Free

{

void operator()(T* _ptr)//重載(),可以像函數一樣使用這個類

{

cout << "Free _ptr" << endl;

free(_ptr);

}

};


template <typename T>//定製刪除器(文件)

struct Fclose

{

void operator()(T* _ptr)

{

cout << "Fclose _ptr" << endl;

fclose(_ptr);

}

};

void testDel()

{

SharedPtr<int, Del<int>> sp1(new int(1));

SharedPtr<int, Free<int>> sp2((int*)malloc(sizeof(int)));

FILE* fp = fopen("yxt.txt", "r");

SharedPtr<FILE, Fclose<FILE>> sp3(fp);

}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章