boost::scoped_ptr雖然簡單易用,但它不能共享所有權的特性卻大大限制了其使用範圍,而boost::shared_ptr可以解決這一侷限。顧名思義,boost::shared_ptr是可以共享所有權的智慧型指標,首先讓我們通過乙個例子看看它的基本用法:
#include
#include
#include
class implementation
void do_something()
};void test()
void main()
該程式的輸出結果如下:
the sample now has 1 references
the sample now has 2 references
after reset sp1. the sample now has 1 references
destroying implementation
after reset sp2.
#include
#include
#include
#include
using namespace boost;
using namespace std;
class implementation
void do_something()
};void test()
可以看到,boost::shared_ptr指標sp1和sp2同時擁有了implementation物件的訪問許可權,且當sp1和sp2都釋放對該物件的所有權時,其所管理的的物件的記憶體才被自動釋放。在共享物件的訪問許可權同時,也實現了其記憶體的自動管理。
boost::shared_ptr的記憶體管理機制:
boost::shared_ptr的管理機制其實並不複雜,就是對所管理的物件進行了引用計數,當新增乙個boost::shared_ptr對該物件進行管理時,就將該物件的引用計數加一;減少乙個boost::shared_ptr對該物件進行管理時,就將該物件的引用計數減一,如果該物件的引用計數為0的時候,說明沒有任何指針對其管理,才呼叫delete釋放其所佔的記憶體。
上面的那個例子可以的圖示如下:
sp1對implementation物件進行管理,其引用計數為1
增加sp2對implementation物件進行管理,其引用計數增加為2
sp1釋放對implementation物件進行管理,其引用計數變為1
sp2釋放對implementation物件進行管理,其引用計數變為0,該物件被自動刪除
boost::shared_ptr的特點:
和前面介紹的boost::scoped_ptr相比,boost::shared_ptr可以共享物件的所有權,因此其使用範圍基本上沒有什麼限制(還是有一些需要遵循的使用規則,下文中介紹),自然也可以使用在stl的容器中。另外它還是執行緒安全的,這點在多執行緒程式中也非常重要。
boost::shared_ptr的使用規則:
boost::shared_ptr並不是絕對安全,下面幾條規則能使我們更加安全的使用boost::shared_ptr:
避免對shared_ptr所管理的物件的直接記憶體管理操作,以免造成該物件的重釋放
shared_ptr並不能對迴圈引用的物件記憶體自動管理(這點是其它各種引用計數管理記憶體方式的通病)。
不要構造乙個臨時的shared_ptr作為函式的引數。
如下列**則可能導致記憶體洩漏:
void
test()
正確的用法為:
void test()
#include "boost/shared_ptr.hpp"
#include
#include
using namespace std;
using namespace boost;
class a ;};
class b : public a
};boost::shared_ptrcreatea()
int main()
std::cout << "the choir is gathered: \n";
for (vector>::iterator it=container.begin();it!=container.end();++it)
}shared_ptr是典型的資源獲取即初始化技術。不過shared_ptr採用了更複雜一點raii方式,因為它實現了引用計數。當建立資源的時候將它放入乙個shared_ptr, shared_ptr內部記錄對這種資源的引用次數為1次。當這個shared_ptr物件離開作用域時,引用次數減1,shared_ptr物件析構時,檢查到引用次數為0了,就銷毀資源:
//pint離開作用域, 所以new int(14)被引用次數為0. 指標被銷毀。防止了
此處及以下assert**都會判斷成功。如果......跳出異常。那麼pint也離開了作用域,指標照常還是被銷毀,所以智慧型指標可以有效防止資源洩露。
boost::shared_ptrpint2;
assert(pint2.use_count() == 0); // temp2還沒有引用指標
boost::shared_ptrpint1(new int(14));
assert(pint1.use_count() == 1); // new int(14)這個指標被引用1次
pint2 = pint1;
assert(pint1.use_count() == 2); // new int(14)這個指標被引用2次
assert(pint2.use_count() == 2);
} //pint1離開作用域, 所以new int(14)被引用次數-1
assert(pint2.use_count() == 1);
} // pint2離開作用域,引用次數-1,現在new int(14)被引用0次,所以銷毀它
不管資源曾經被多少次引用。當它被引用0次時就會銷毀。
1.3在shard_ptr使用中經常會發現,乙個物件會有兩次被析構的情況。其實這種是因為那個物件指標被兩次當成shard_ptr建構函式裡的引數。一定要避免這種現象。考慮如下**:
// temp1,temp2都離開作用域,它們都銷毀pint. pint被銷毀了兩次!系統終於崩潰了 -_-
正確的做法是將原始指標賦給智慧型指標後,以後的操作都要針對智慧型指標了.
// temp1,temp2都離開作用域,引用次數變為0,指標被銷毀
1.4如果資源的建立銷毀不是以new,delete的方式建立銷毀怎麼辦?shared_ptr也可以指定刪除器:
// filecloser.h filecloser刪除器
class filecloser}};
// 某實現檔案
1.5shared_ptr已經被即將到來的標準庫技術報告所採納,將成為tr1中的一員。為了以後更好的移植現有**到c++新標準中。可以使用乙個namespace的乙個小技巧,在標頭檔案stdafx.h中宣告(參考
effective c++ item 54):
namespace std
namespace tr1 = ::boost; // namespace std::tr1 is an alias
} // for namespace boost
這樣就可以用如下方法寫**:
std::tr1::shared_ptrpint(new int(14));
#include
#include
#include
using namespace boost;
using std::cout;
using std::endl;
using std::auto_ptr;
class a
總結引用計數智慧型指標是非常重要的工具。boost的 shared_ptr
提供了堅固而靈活的解決方案,它已被廣泛用於多種環境下。需要在使用者之間共享物件是常見的,而且通常沒有辦法通知使用者何時刪除物件是安全的。shared_ptr
讓使用者無需知道也在使用共享物件的其它物件,並讓它們無需擔心在沒有物件引用時的資源釋放。這對於boost的智慧型指標類而言是最重要的。你會看到boost.smart_ptr中還有其它的智慧型指標,但這乙個肯定是你最想要的。通過使用定製刪除器,幾乎所有資源型別都可以存入 shared_ptr
。這使得shared_ptr
成為處理資源管理的通用類,而不僅僅是處理動態分配物件。與裸指標相比,shared_ptr
會有一點點額外的空間代價。我還沒有發現由於這些代價太大而需要另外尋找乙個解決方案的情形。不要去建立你自己的引用計數智慧型指標類。沒有比使用 shared_ptr
智慧型指標更好的了。
在以下情況時使用 shared_ptr
:
int main()
// temp1,temp2都離開作用域,它們都銷毀pint. pint被銷毀了兩次!系統終於崩潰了 -_-
}
boost 智慧型指標
boost shared ptr 的記憶體管理機制 boost shared ptr 的管理機制其實並不複雜,就是對所管理的物件進行了引用計數,當新增乙個 boost shared ptr 對該物件進行管理時,就將該物件的引用計數加一 減少乙個 boost shared ptr 對該物件進行管理時,...
boost 智慧型指標
最近使用boost的智慧型指標,檢視了一些帖子。總結如下 智慧型指標分類 智慧型指標使用注意事項 多執行緒安全性分析 這個帖子的結論很好,1 shared ptr是乙個非常實用的智慧型指標。2 shared ptr的實現機制是在拷貝構造時使用同乙份引用計數。3 對同乙個shared ptr的寫操作不...
boost 智慧型指標
shared 指標類似於乙個帶計數器的指標,當指標計數次數為0時,它將自動析構物件。shared ptr指標可通過一次new出來,一直向下傳遞,直到每次析構shared ptr時將該指標引用量 1 注 每次進行不帶引用的傳遞時呼叫次數會加1,但析構時同時會 1,若用引用傳遞,每次呼叫值不增加,但同樣...