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)