boost庫的第二類智能指標是shared_ptr。
shared_ptr的特點是:
一、 它可以指向相同的內容,靠引用計數來決定內容是否釋放。其中new int申請的空間,在三個指向它的指標全部釋放時才被釋放,否則只是引用計數減一。
#include <cassert>#include <boost/shared_ptr.hpp>int _tmain(int argc, _TCHAR* argv[]){boost::shared_ptr<int> tmp(new int(50));boost::shared_ptr<int> a = tmp;boost::shared_ptr<int> b = tmp;*a = 100;assert(*b == 100);getchar();return 0;}
二、 能作為容器元素來使用。
#include <iostream>#include <vector>#include <boost/shared_ptr.hpp>class counter{public:static int _no;counter(){_no++;}~counter(){_no--;}static void Speak(){std::cout << "Total " << _no << " Objects!" << std::endl;}};int counter::_no = 0;int _tmain(int argc, _TCHAR* argv[]){typedef boost::shared_ptr<counter> element;typedef std::vector<element> container;typedef std::vector<element>::iterator iterator;element a(new counter());element b(new counter());element c(new counter());element d(new counter());element e(new counter());container cr;cr.push_back(a);cr.push_back(b);cr.push_back(c);cr.push_back(d);cr.push_back(e);for (iterator it = cr.begin(); it != cr.end(); ++it){(*it)->Speak();}cr.clear();getchar();return 0;}
三、 shared_ptr可以定製刪除器,來處理非delete和delete[]能夠處理的資源,如樣本中的檔案描述符等。下面兩個例子照抄說明書。
shared_ptr指向指標時,原來的指標調用方式為:&*sp,*sp表示是對象,&(*sp)代表是指標。可以用sp.get()來替代。
#include "boost/shared_ptr.hpp"#include <vector>#include <cassert>#include <iostream>#include <cstdio>class FileCloser{public:void operator()(FILE* file){std::cout << "The FileCloser has been called with a FILE*, which will now be closed.\n";if (file != 0){std::fclose(file);}}};int _tmain(int argc, _TCHAR* argv[]){{// 在此範圍內檔案開啟會自動關閉FILE *f = std::fopen("test.txt", "r");if (f == 0){std::cout << "Unable to open file\n";throw "Unable to open file";}boost::shared_ptr<FILE> sf(f, FileCloser());std::fseek(sf.get(), 100, SEEK_SET);std::fseek(&*sf, 100, SEEK_SET);}std::cout << std::endl;}
第二個例子示範了安全刪除器的方法,並且示範了刪除函數的規則:實現operator()(TYPE *p){}函數。
#include "boost/shared_ptr.hpp"#include <iostream>class A {// 嵌套類class deleter { public:// 重載運算子()void operator()(A* p) { delete p; } };// 聲明為友元類,再進行嵌套實現,實現了安全訪問。friend class deleter;public: virtual void sing() { std::cout << "Lalalalalalalalalalala"; }// 構造器static boost::shared_ptr<A> createA() { boost::shared_ptr<A> p(new A(),A::deleter());return p; }protected: virtual ~A() {};};int main() {// 建構函式建立出來一個類,然後直接調用,不用管理釋放的任何操作。boost::shared_ptr<A> p=A::createA();}
總結一下,shared_ptr的使用方式:
1 對一個對象無所有權的情況下,多次指標引用,這是哪個指標釋放資源都會導致其他指標變成野指標,所以採用shared_ptr來規避這個問題,shared_ptr採用引用計數的方法只有在最後一個指標釋放時才釋放資源,其他情況只是引用計數減一。
2 它適用於容器類,正因為它有1的特性,才適用於容器類,這是與scoped_ptr很主要的特性區別。
3 它可以根據引用的內容來定製刪除函數,有些情況下,delete和delete[]並不是登出資源的方式的時候,需要使用shared_ptr的定製刪除函數的功能,刪除規則和刪除方法見範例程式碼。
4 shared_ptr很適用於對象沒有所有權的情況下,所以特別適用於工廠類和構造器等設計模式,而且天生就為此實現。代碼二可以建立一個構造器函數來實現每個對象的建立(自己可以修改一下)。
5 當要傳送對象到庫或從庫擷取對象,而沒有明確的所有權時(這句話是資料上的原話,我沒有理解具體的應用情況,照抄下來)
6 當管理一些需要特殊清除方式的資源時(這句話是資料上的原話,內容如3)