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)