一、介绍

shared_ptr包装了new操作符在堆上分配的动态对象,但他实现的是计数型的智能指针,shared_ptr早期的名字就是counter_ptr,可以自由拷贝和赋值,在任意的地方共享它,当没有代码使用(引用计数为0时)它才删除被包装的动态分配的对象。shared_ptr也可以安全地放到标准容器中,是在STL容器中存储指针最标准的解法。

template<class T>
class shared_ptr
{public:typedef T element_type;                     //内部类型定义shared_ptr();template<class Y> explicit shared_ptr(y*p); //构造函数template<classY,class D> shared_ptr(Y*p,D d);~shared_ptr();                              //析构函数shared_ptr(shared_ptr const &r);          //拷贝构道template<class Y> explicit shared_ptr(std::auto_ptr<Y> &r);shared_ptr & operator=(shared_ptr const &r); //赋值操作template<class Y> shared_ptr & operator=(shared_ptr<Y> const&r); template<class Y> shared ptr & operator=(std::autoptr<y> & r);void reset();                                 //重置智能指针template<class Y> void reset(Y*p);template<class Yclass D> void reset(Y*p, D d);T & operator*() const;                      //操作符重载T * operator->() const;                   //操作符重载T * get() const;                             //获得原始指针bool unique() const;                        //是否唯一long use_count() const;                   //引用计数operator bool()const;                         //bool值转型void swap(shared_ptr &b);                  //交换指针
};

shared_ptr与scoped_ptr同样是用于管理new动态分配对象的智能指针,因此功能上有很多相似之处:它们都重载了*和->操作符以模仿原始指针的行为,提供隐式bool类型转换以判断指针的有效性,get可以得到原始指针(return px),并且没有提供指针算数操作。

shared_ptr<int> spi(new int);
assert(spi);
*spi = 253;
shared_ptr<string> sps(new string("smart"));
assert(sps->size() == 5);

shared_ptr有多种形式构造函数,应用于各种可能的情形:

  • 无参的shared_ptr()创建一个持有空指针的shared_ptr;
  • shared_ptr(Y* p)获得指向类型T的指针p的管理权,同时引用计数置为1.这个构造函数要求Y类型必须能够转换为T类型
  • shared_ptr(shared_ptr const & r)从另外一个shared_ptr获得指针的管理权,同时引用计数加1,结果是两个shared_ptr共享一个指针的管理权;
  • shared_ptr(std::auto_ptr< Y> &r)从另外一个auto_ptr获得指针的管理权,引用计数置为1,同时auto_ptr自动失去管理权;
  • operator=赋值操作符可以从另外一个shared_ptr或auto_ptr获得指针的管理权,其行为同构造函数
  • shared_ptr(Y *p, D d)行为类似shared_ptr(Y *p),但是用参数d指定了析构时定值删除器,而不是简单的delete。

shared_ptr的reset()函数与scoped_ptr也不尽相同。它的作用是将引用计数减1,停止对指针的共享,除非引用计数为0,否则不会发生删除操作。带参数的reset()则是类似相同形式的构造函数,原指针引用计数减1的同时改为管理另一个指针。

shared_ptr有两个专门的函数检查引用计数。unique()检查shared_ptr是指针唯一所有者返回true,use_count()返回当前引用计数。use_count()应该仅用于测试或调试,它不提供高效的操作,而且有可能是不可用的(极少数情形)。

shared_ptr还支持比较运算,可以测试两个shared_ptr的相等或不相等,比较基于内部保存的指针,相当于a.get()==b.get()。shared_ptr还可以使用operator<比较大小。同样基于内部保存的指针,但不提供除operator<之外的比较操作符,这使得shared_ptr可以被用于标准关联容器(set和map)

shared_ptr的类型转换不能使用static_cast之流,只能使用shared_ptr自己提供的转型函数:static_pointer_cast()、const_pointer_cast()、dynamic_pointer_cast()和reinterpret_cast()函数,它们转型后返回的是shared_ptr类型。

如下使用static_pointer_cast ,dynamic_pointer_cast对bad_exception,std::exception做类型转换赋值。

shared_ptr<std::exception> sp1(new bad_exception("error"));
shared_ptr<bad_exception> sp2 = dynamic_pointer_cast<bad_exception>(sp1);
shared_ptr<std::exception> sp3 = static_pointer_cast<std::exception>(sp2);

此外,shared_ptr还支持流输出操作符operator<<,输出内部指针值,方便调试。
代码实现如下:

template<class T, class U> inline bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_NOEXCEPT
{return a.owner_before( b );
}template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b) BOOST_NOEXCEPT
{a.swap(b);
}template<class T, class U> shared_ptr<T> static_pointer_cast( shared_ptr<U> const & r ) BOOST_NOEXCEPT
{(void) static_cast< T* >( static_cast< U* >( 0 ) );typedef typename shared_ptr<T>::element_type E;E * p = static_cast< E* >( r.get() );return shared_ptr<T>( r, p );
}template<class T, class U> shared_ptr<T> const_pointer_cast( shared_ptr<U> const & r ) BOOST_NOEXCEPT
{(void) const_cast< T* >( static_cast< U* >( 0 ) );typedef typename shared_ptr<T>::element_type E;E * p = const_cast< E* >( r.get() );return shared_ptr<T>( r, p );
}template<class T, class U> shared_ptr<T> dynamic_pointer_cast( shared_ptr<U> const & r ) BOOST_NOEXCEPT
{(void) dynamic_cast< T* >( static_cast< U* >( 0 ) );typedef typename shared_ptr<T>::element_type E;E * p = dynamic_cast< E* >( r.get() );return p? shared_ptr<T>( r, p ): shared_ptr<T>();
}template<class T, class U> shared_ptr<T> reinterpret_pointer_cast( shared_ptr<U> const & r ) BOOST_NOEXCEPT
{(void) reinterpret_cast< T* >( static_cast< U* >( 0 ) );typedef typename shared_ptr<T>::element_type E;E * p = reinterpret_cast< E* >( r.get() );return shared_ptr<T>( r, p );
}

二、用法示例:

 shared_ptr<int> sp(new int(10); //一个指向整数的shared ptrassert(sp.unique)): //现在shared_ptr是指针的唯一持有者shared_ptr<int> sp2 - sp; //第二个shared_ptr,拷贝构造函数//两个shared_ptr相等,指向同一个对象,引用计数为 2 assert(sp sp2 .. sp.use count() 2);*sp2=100; //使用解引用操作符修改被指对象assert(*sp w*100): //另一个sharedptr也同时被修改sp.reset(); //停止 shared_ptr 的使用assert(!sp); //sp不再持有任何指针(空指针)//第二个例子示范了shared_ptr较复杂的用法:class shared //一个拥有shared_ptr的类
(
privater://shared_ptr 成员变量shared ptr<int> p;
public:shared(shared_ptr<int>P_):P(P_){} //构造承数初始化shared_ptrvoid print() //输出 shared ptr 的引用计数和指向的值{cout <<"count:" << p.use_count()<<x "v =" <<*p << endl;}
1;
//使用shared ptr 作为函数参数void print func(shared ptr<int p){//同样输出 shared_ptr 的引用计数和指向的值 cout << "count;" << p.use_count()<<" v=" <<*p <<endl;int main(){shared ptr<int>p(new int(100)):shared s1(p),s2(p); //构造两个自定义类s1.print();s2.print();*p = 20: //修改shared_ptr所指的值print_func(p);s1.print();}

运行结果:

count:3 v=100
count:3 v=100
count:4 v=20
count:3 v=20

这段代码定义了一个类和一个函数,两者都接受share_ptr 对象作为参数,特别注意的是我们没有使用引用的方式传递参数,而是直接拷贝,就像是在使用一个元素指针,,share_ptr支持这样的用法。
在声明了share_ptr和两个shared示例后,指针被他们所共享因此引用计数为3,print_func()函数内部拷贝了一个share_ptr对象,因此引用计数再增加1,当退出函数时拷贝自动析构,引用计数又减为3。

三、工厂函数make_shared

share_ptr提供了一个自由工厂函数make_shared(),来消除显示的new调用,make_shared()函数接受若干个参数,然后把他们传递给类型T的构造函数,创建一个share_ptr的对象并返回。通常make_shared()函数比直接创建share_ptr对象的方式快且高效。因为它内部仅分配一次内存,消除了share_ptr构造时的开销。

int main()
{shared_ptr<string> sp = make_shared<string>("make_shared");shared_ptr<vector<int>> spv = make_shared<vector<int> >(10,2);assert(spv->size() == 10);
}

四、应用于标准容器

有两种方法可以将share_ptr应用于标准容器(或者容器适配器等其他容器),一种方法是将容器作为share_ptr管理的对象,即share_ptr<list>,使容器可以安全地共享。这个比较常用。
另一种是将share_ptr作为容器的元素。如vector<shared_ptr>,因为share_ptr支持拷贝语义和比较操作,符合容器对元素的要求,所以可以在容器中安全地容纳元素的指针而不是拷贝

#include <boost/make shared.hpp>
int main()
{typedef vector<shared_ptr<int>> vs; //一个持有shared_ptr 的标准容器类型vs v(10);                          //声明一个拥有10个元素的容器。元素被//初始化为空指针int i = 0;for(vs::iterator pos = v.begin():pos != v.end(): ++pos){(*pos) = make_shared<int>(++i); //使用工厂函数赋值cout << *(*pos)<<",";       //输出值}cout << endl;shared_ptr<int> p = v[9];*p = 100;cout <<*v[9] << endl;}

引用资料:
《Boost程序库完全开发指南–深入C++“准”标准库(第2版)》
作者:罗剑锋

boost shared_ptr基本用法介绍相关推荐

  1. boost::shared_ptr用法测试程序

    boost::shared_ptr用法测试程序 实现功能 C++实现代码 实现功能 boost::shared_ptr用法测试程序 C++实现代码 #include <boost/config. ...

  2. boost学习之boost::shared_ptr

    Boost智能指针--shared_ptr boost::scoped_ptr虽然简单易用,但它不能共享所有权的特性却大大限制了其使用范围,而boost::shared_ptr可以解决这一局限.顾名思 ...

  3. c++ stl容器vector删除(erase),遍历等基本用法介绍及头文件

    Vectors 包含着一系列连续存储的元素,其行为和数组类似.访问Vector中的任意元素或从末尾添加元素都可以在常量级时间复杂度内完成,而查找特定值的元素所处的位置或是在Vector中插入元素则是线 ...

  4. boost::log::core用法的测试程序

    boost::log::core用法的测试程序 实现功能 C++实现代码 实现功能 boost::log::core用法的测试程序 C++实现代码 #include <boost/smart_p ...

  5. boost::function的用法(一)

    boost::function的用法 本片文章主要介绍boost::function的用法. boost::function 就是一个函数的包装器(function wrapper),用来定义函数对象 ...

  6. awk 和sed的用法介绍

    awk 和sed的用法介绍 一.awk的介绍 1. 作用及用法要求 2. 使用方法 (1)使用的命令: (2)举例说明: 二.sed的介绍 1. 用法介绍及常用命令 2. 具体使用 一.awk的介绍 ...

  7. Scanpy(一)AnnData数据结构与一些API用法介绍

    目录 Scanpy简介与安装 AnnData AnnData的结构 h5ad:AnnData的写入和读取 Scanpy中一些常用api的用法介绍 sc.pp.filter_cells sc.pp.fi ...

  8. php中使用mysql的视图_MYSQL中视图的用法介绍(代码示例)

    本篇文章给大家带来的内容是关于MYSQL中视图的用法介绍(代码示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 1.什么是视图 执行一条SQL,将结果集保存在一张虚拟表中 (相关 ...

  9. pm2常用的命令用法介绍

    pm2 是一个带有负载均衡功能的Node应用的进程管理器.当你要把你的独立代码利用全部的服务器上的所有CPU,并保证进程永远都活着,0秒的重载, PM2是完美的,下面我们来看pm2常用的命令用法介绍吧 ...

最新文章

  1. 你以为的周末 vs 实际上的周末
  2. Android应用程序模块:应用、任务、进程和线程
  3. cmake (2)其他指令
  4. Django09:图书管理系统笔记/choices用法/ MTV与MVC模型/多对多三种创建方式
  5. jQuery 基础教程 (二)之jQuery对象与DOM对象
  6. Vtk出现Generic Warning时
  7. 选择座位html,影厅座位预览效果(css3)_html/css_WEB-ITnose
  8. java 难题_您可以避免的6种组织成长难题
  9. 学校为什么要单位接收函_为什么要选择语言学校留学?
  10. 支持向量机在风控竞赛数据集上的应用
  11. KHV0031-himall3.0商城异常类(二)
  12. 【第152期】游戏策划:给@不五的简历分析
  13. Linux 语言包的安装
  14. opengl光照效果之点光源
  15. Android热修复技术——QQ空间补丁方案解析(1)
  16. 「运维有小邓」搜索日志数据以作为网络安全情报
  17. Python|几十行代码带你简单实现模拟浏览器操作
  18. 基于at89c51单片机的led数字倒计时器设计c语言,课程设计(论文)-基于AT89C51单片机的LED数字倒计时器设计.docx...
  19. Scaling Apps with Varnish
  20. 穹顶之下,我们该何去何从?

热门文章

  1. 破解navicat试用期功能
  2. Python入门习题大全——以特殊方式跟管理员打招呼
  3. 小明哥学linux驱动之USB-OTG(基于gadget框架)
  4. word文档转excel表格
  5. 大数据和高并发解决方案
  6. html5 像素风画板,使用Canvas和JavaScript做一个画板
  7. Meta推出VR头显,是谁的“福”与“祸”?
  8. nginx反向代理tcp
  9. EDI的五个常见挑战以及如何克服这些挑战
  10. 大可乐玩众筹花样作死:山寨、抄袭动摇根基