参考《boost程序库完全开发指南》
//func_eg.h
//定义了所有的示例函数
#pragma once #include<iostream> #include<boost\smart_ptr.hpp> #include<vector> using namespace boost; void eg(); void eg1(); void eg2(); void eg3(); void eg4(); void eg_make_shared(); void eg5(); void eg_shared_array(); void eg_weak_ptr(); void eg_shared_from_this();//shared_ptr.cpp
//示例shared_ptr的构造函数
#include"func_eg.h" /* shared_ptr同样用于管理new动态分配内存对象的指针,重载了*和->操作符模仿指针操作。 shared_ptr与scoped_ptr不同的是shared_ptr可以被共享,有正常的拷贝,赋值语义,也可以进行shared_ptr之间的比较 shared_ptr的构造函数: 1.无参的shared_ptr创建一个持有空指针的shared_ptr 2.shared_ptr(Y * p)获得指向类型T的指针p的管理权,同时引用计数置为1.这个构造函数要求Y类型必须能转换为T类型。 3.shared_ptr(shared_ptr const &r)从另外一个shared_ptr指针获得指针的管理权,同时atuo_ptr失去管理权 4.operator=可以从另一个shared_ptr或auto_ptr获得指针的管理权 5.shared_ptr(Y * p,D d)行为类似shared_ptr(Y * p),但使用参数d指定了析构时的定制删除器。 shared_ptr的reset()函数作用是将引用计数减一,停止对指针的共享,除非引用计数为0,否则不会发生删除操作。 带参数的reset()函数原指针引用计数减一,同时改为管理另一个指针 unique()函数若当前shared_ptr是指针的唯一所有者时返回true,use_count返回指针的引用计数 两个shared_ptr可以进行比较,比较的结果是由两个shared_ptr保存的内部指针a和b决定的,相当于a.get() == b.get() shared_ptr还可以使用<比较大小,同样基于内部保存的指针,但不提供<以外的比较操作符,这使得shared_ptr可以被用于标准关联容器 typedef shared_ptr<string> sp_t; map<sp_t,int> m; //标准映射容器 sp_t sp(new string("one")); m[sp] = 111; //关联数组用法 在编写基于虚函数的多态代码时指针的类型转换很有用,比如把一个基类的指针转换成子类指针或者反过来, 但对于shared_ptr不能使用诸如static_cast<T*>(p.get())的形式,将导致转换类型后的指针无法再被shared_ptr正确管理。 为了支持这样的用法,shared_ptr提供了static_pointer_cast<T>(),const_pointer_cast<T>(),dynamic_pointer_cast<T>(), 返回的是转换类型后的shared_ptr shared_ptr<std::exception> sp1(new bad_exception("error")); shared_ptr<std::bad_exception> sp2 = dynamic_pointer_cast<bad_exception>(sp1); shared_ptr<std::exception> sp3 = static_pointer_case<std::exception>(sp2); 此外,shared_ptr还支持operator<<,输出内部的指针值 */ //用法一 void eg(){ shared_ptr<int> sp1(new int); //构造函数2 assert(sp1.unique()); shared_ptr<int> sp2 = sp1; //构造函数3,第二个shared_ptr,拷贝构造函数,两个shared_ptr指向一个对象,引用计数为2 assert(sp1 == sp2 && sp1.use_count() == 2); shared_ptr<int> sp3(sp1); std::cout << "sp3's use count:" << sp3.use_count() << std::endl; *sp2 = 10; //使用解引用操作符修改被指对象 assert(*sp1 == 10); //另一个shared_ptr同时被修改 /* shared_ptr的reset()函数作用是将引用计数减一,停止对指针的共享,除非引用计数为0,否则不会发生删除操作。 带参数的reset()函数原指针引用计数减一,同时改为管理另一个指针 */ sp1.reset(); //停止shared_ptr的使用 assert(!sp1); //sp1不再持有任何指针 }
//shared_ptr1.cpp
//示例了shared_ptr的构造函数用法
#include"func_eg.h" class shared { private: std::shared_ptr<int> p; public: shared(std::shared_ptr<int> p_) :p(p_) {} //构造函数初始化shared_ptr void print() { std::cout << "count:" << p.use_count() << ",value = " << *p << std::endl; } }; void print_func(std::shared_ptr<int> p) { std::cout << "count:" << p.use_count() << ",value = " << *p << std::endl; } void eg1() { std::shared_ptr<int> p(new int(20)); shared p1(p), p2(p); //3.shared_ptr(shared_ptr const &r)从另外一个shared_ptr指针获得指针的管理权,同时atuo_ptr失去管理权 p1.print(); //count:3,value = 20; p2.print(); //count:3,value = 20; *p = 30; print_func(p); //count:4,value = 30;在print_func内部拷贝了一个shared_ptr对象,因此引用计数加一,函数退出时自动析构 p1.print(); //count:3,value = 30; }
//shared_ptr2.cpp
//示例shared_ptr用于标准容器
#include"func_eg.h" /* 将shared_ptr应用于标准容器: 一、将容器作为shared_ptr的管理对象,如shared_ptr<list<T>>,使容器可以被安全的共享,用法与普通的shared_ptr没有区别 二、将shared_ptr作为容器的元素,如vector<shared_ptr<T>>,因为shared_ptr支持拷贝语义和比较操作,符合标准容器对元素的要求 */ void eg2() { typedef std::vector<std::shared_ptr<int>> vs; //一个持有shared_ptr的标准容器类型 vs v(10); //声明一个有10个元素的容器,元素被初始化为空指针 int i = 0; for (vs::iterator pos = v.begin(); pos != v.end(); ++pos) { (*pos) = std::make_shared<int>(++i); //使用工厂函数赋值 std::cout << *(*pos) << ","; //输出值,容器存储的是shared_ptr,所以*pos是shared_ptr类型,然后*shared_ptr才是值 } std::cout << std::endl; std::shared_ptr<int> p = v[9]; *p = 100; std::cout << std::endl << "count:" << p.use_count() << std::endl; for (vs::iterator pos = v.begin(); pos != v.end(); ++pos) { std::cout << *(*pos) << ","; //输出值 } }
//示例了工厂模式创建shared_ptr对象
#include"func_eg.h" /*应用于工厂模式*/ /* 工厂模式是一种创建型设计模式,这个模式包装了new操作符,使对象的创建工作集中在 工厂类或者工厂函数中 从而更容易适应变化,make_shared就是工厂模式的一个例子 */ class abstrac { public: virtual void f() = 0; virtual void g() = 0; protected: ~abstrac() {} //析构函数设为受保护成员,说明除了类和它的子类,其余的类无法删除该类对象 }; class imp1 :public abstrac { virtual void f() { std::cout << "imp1 f" << std::endl;} virtual void g() { std::cout << "imp1 g" << std::endl; } }; /*工厂模式返回指向分配内存产生的对象的指针,返回一个shared_ptr类型指针可以方便内存管理*/ std::shared_ptr<abstrac> create() { return std::shared_ptr<abstrac>(new imp1); } void eg4() { std::shared_ptr<abstrac> p = create(); //创建对象的时候,不用直接显示调用new操作符,而是调用了用户自定义的创建函数 p->f(); p->g(); }//make_shared.cpp
//示例了make_shared构造shared_ptr的方法
#include"func_eg.h" /* shared_ptr消除了显示的delete调用,但是shared_ptr的构造还要调用new函数,使用工厂模式来解决 template<class T,class....Args> shared_ptr<T> make_shared(...) make_shared()最多可以接受10个参数,然后把它们传递给类型T的构造函数,创建一个shared_ptr<T>对象并放回。 */ void eg_make_shared() { std::shared_ptr<std::string> sp = std::make_shared<std::string>("make_shared"); //string的构造函数接受一个参数,因此括号中只有一个参数 std::shared_ptr<std::vector<int> > spv = std::make_shared<std::vector<int>>(10, 2); //vector的构造函数可以接受两个参数,因此括号中可以有两个参数 std::cout << sp.use_count() << " " << *sp << std::endl; std::cout << spv.use_count() << std::endl; for (std::vector<int>::iterator i = spv->begin(); i != spv->end(); ++i) { std::cout << *i; } std::cout << std::endl; }
//示例的定制删除器的用法
//因为shared_ptr能够存储void*类型的指针,而void*类型又可以指向任意类型,因此shared_ptr就像一个泛型的指针容器
#include"func_eg.h" /*定制删除器*/ /* shared_ptr(Y * p,D d);第一个参数是要被管理的指针,第二个参数d则告诉shared_ptr在析构时不是使用delete来操作指针p 而要用d来操作,即把delete(p)换成d(p)。 d可以是一个函数对象,也可以是一个函数指针。 对删除器的要求是能拷贝,不发出异常。 为了配合删除器工作,shared_ptr提供一个自由函数get_deletee(shared_ptr<T> & p),它能够返回指向删除器的指针 有了删除器的概念,可以用shared_ptr实现管理任意资源,只要这种资源提供了自己的释放操作,shared_ptr就能保证自动释放 */ int * create(int k) { std::cout << "创建" << k << std::endl; int * t = new int(k); return t; } void del(int *p) { //删除函数的参数是指向要操作的对象的指针 std::cout << "删除" << *p; } void eg5() { int *p = create(2); std::shared_ptr<int> p1(p,del); }