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)