shared_ptr

来源:互联网 发布:linux ftp put命令 编辑:程序博客网 时间:2024/09/21 06:21

参考《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_ptr2.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_ptrshared_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指向一个对象,引用计数为2assert(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_ptrvoid 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_ptr3.cpp

//示例了工厂模式创建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_ptr5.cpp

//示例的定制删除器的用法

//因为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);}






0 0
原创粉丝点击