標籤:釋放 end .cpp mil 平台 false ++ rgb win
眾所周知。C++中對堆記憶體的申請與釋放全然由使用者來控制,這就造成使用者在使用的時候常常造成記憶體流失、野指標、反覆釋放等常見的掛掉問題,所以我們有必要提供一套機制。使得使用者僅僅需申請對應的記憶體,不用管釋放的問題,事實上這屬於著名的RAII(Resource Acquisition Is Initialization)技術 。在C++中這樣的技術稱作“智能指標”,C++中的智能指標技術越來越受到廣泛應用。以下簡要介紹下智能指標。
從以上描寫敘述中能夠看出,我們須要提供一套記憶體顯式申請與隱式釋放,並向使用者屏蔽這些細節的機制,對於這樣的隱藏細節的做法。我們一般會用一個控制代碼類來封裝。
在這裡控制代碼類就是我們提供給使用者的智能指標類。
智能指標為何“智能”呢?這裡就涉及到還有一項重要技術”引用計數“。當有N個智能指標控制代碼類指向同一段記憶體,這時就會將這段記憶體的引用計數設定為N,每噹噹中的一個控制代碼離開範圍時會自己主動調用解構函式。將記憶體引用計數減一,這樣當某個智能指標控制代碼類的引用計數為1時,表示這段記憶體僅僅有該控制代碼指向它。
在這個過程中。解構函式起非常大的作用,RAII技術也是基於解構函式而實現的。
說了這麼多,直接看代碼:
/* * refcount.h 引用計數 *[email protected] */#ifndef _REFCOUNT_H_#define _REFCOUNT_H_class RefCount{public:RefCount() : use(new size_t(1)){}RefCount(const RefCount &refcnt) : use(refcnt.use){inc();}~RefCount(){if (decr() == 0){delete use;}}RefCount & operator=(const RefCount &refcnt){if (decr() == 0){delete use;}use = refcnt.use;inc();return *this;}void init(){use = new size_t(1);}bool only(){return *use == 1;}inline size_t inc(){return ++*use;}inline size_t decr(){return --*use;}bool reattach(const RefCount &refcnt){++*refcnt.use;if (only()){delete use;use = refcnt.use;return true;}else{--*use;use = refcnt.use;return false;}}private:size_t *use;};#endif // _REFCOUNT_H_
/* * smartpointer.h 智能指標 *[email protected] */#ifndef _SMARTPOINTER_H_#define _SMARTPOINTER_H_#include "refcount.h"template <typename T>class SmartPtr{public:SmartPtr() : ptr_(new T){refcnt_.init();}SmartPtr(const T & obj) : ptr_(new T(obj)){}SmartPtr(T * pobj) : ptr_(pobj){//refcnt_初始化時,*use = 1if (pobj == nullptr){refcnt_.decr();}}SmartPtr(const SmartPtr &spnt) : ptr_(spnt.ptr_), refcnt_(spnt.refcnt_){}~SmartPtr(){if (refcnt_.only()){delete ptr_;ptr_ = nullptr;}}SmartPtr & operator=(const SmartPtr &spnt){//這一步相當於對refcnt_進行賦值if (refcnt_.reattach(spnt.refcnt_)){delete ptr_;}ptr_ = spnt.ptr_;return *this;}T * operator->(){return ptr_;}private:T * ptr_;RefCount refcnt_;};#endif // _SMARTPOINTER_H_
/* * main.cpp 測試程式 *[email protected] */#include "memleakcheck.h"#include "smartpointer.h"#include <iostream>#include <string>#include <boost/shared_ptr.hpp>int main(void){{SmartPtr<int> sp(2);SmartPtr<int> sp2(sp);SmartPtr<int> sp3(3);sp = sp3;sp2 = sp3;}{SmartPtr<std::string> sp("123");SmartPtr<std::string> sp2(sp);SmartPtr<std::string> sp3("abc");sp = sp3;sp2 = sp3;}{SmartPtr<std::string> sp(new std::string("123"));SmartPtr<std::string> sp2(sp);SmartPtr<std::string> sp3(new std::string("abc"));sp = sp3;sp2 = sp3;}{boost::shared_ptr<char> pch(new char[10]);}_CrtDumpMemoryLeaks();return 0;}
memleakcheck.h檔案主要用作VS平台記憶體流失檢測工具,代碼參考於http://blog.csdn.net/windows_nt/article/details/8652191
調試時,發現輸出表單並沒有檢測到記憶體流失。說明智能指標實現正確。main.cpp中還測試了Boost庫中智能指標的使用,能夠看到也是非常方便的,眼下在開源點雲庫PCL中隨處都可見到Boost庫中的智能指標。
以上代碼見github:https://github.com/lming08/Ruminations/
參考資料:
http://www.cnblogs.com/zhangyunkui/archive/2009/11/13/1602514.html
http://blog.csdn.net/windows_nt/article/details/8652191
C++沉思錄
C++中的智能指標