shared_ptr(共享指针)使用总结

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wdxin1322/article/details/23738593
背景介绍        

最近在coding的时候遇到这样的问题,一个两层的map,hashmap<key,map<key,value>>,重新加载时需要将这个map释放,但是这个map使用时是分为两段使用,一段是在hashmap中取出里面的map,第二段是在里层的map中查找key,这在多线程运行时有可能出现在取出里层map的引用后,重新加载数据并且释放掉现在的hashmap,这个场景引起了我对shared_ptr共享指针的关注,言归正传,总结一下shared_ptr。

shared_ptr简介

shared_ptr 主要的功能是,管理动态创建的对象的销毁。它的基本原理就是记录对象被引用的次数,当引用次数为 0 的时候,也就是最后一个指向某对象的共享指针析构的时候,共享指针的析构函数就把指向的内存区域释放掉。共享指针对象重载了 operator* 和 operator-> , 所以你可以像通常的指针一样使用它。

它是引用计数型(reference counting)智能指针,几乎所有的实现都采用在堆(heap)上放个计数值(count)的办法。具体来说,shared_ptr<Foo> 包含两个成员,一个是指向 Foo 的指针 ptr,另一个是 ref_count 指针(其类型不一定是原始指针,有可能是 class 类型),指向堆上的 ref_count 对象。ref_count 对象有多个成员,具体的数据结构如图 1 所示,其中 deleter 和 allocator 是可选的。

shared_ptr 创建

shared_ptr<int> sp(new int(10));                //一个指向整数的shared_ptr    
assert(sp.unique());                            //现在shared_ptr是指针的唯一持有者     
shared_ptr<int> sp2 = sp;                       //第二个shared_ptr,拷贝构造函数     
assert(sp == sp2 && sp.use_count() == 2);       //两个shared_ptr相等,指向同一个对象,引用计数为2    
*sp2 = 100;                                     //使用解引用操作符修改被指对象    
assert(*sp == 100);                             //另一个shared_ptr也同时被修改     
sp.reset();                                     //停止shared_ptr的使用    
assert(!sp);                                    //sp不再持有任何指针(空指针)


1、空shared_ptr

shared_ptr<T> ptr;

2、使用new创建

shared_ptr<T> ptr(new T());

3、使用复制构造函数,或者重载=构造

shared_ptr<T> ptr1(new T()); 
shared_ptr<T> ptr2(ptr1);

或者

shared_ptr<T> ptr1(new T()); 
shared_ptr<T> ptr2;
ptr2 = ptr1;

shared_ptr的线程安全性

shared_ptr 本身不是 100% 线程安全的。它的引用计数本身是安全且无锁的,但对象的读写则不是,因为 shared_ptr 有两个数据成员,读写操作不能原子化。根据文档,shared_ptr 的线程安全级别和内建类型、标准库容器、string 一样,即:

  • 一个 shared_ptr 实体可被多个线程同时读取;
  • 两个的 shared_ptr 实体可以被两个线程同时写入,“析构”算写操作;
  • 如果要从多个线程读写同一个 shared_ptr 对象,那么需要加锁。
使用注意事项

1、shared_ptr可以当做函数的参数,也可以当做函数的返回值,这时候相当于使用复制构造
2、shared_ptr可以被用于标准容器,复制时相当于使用复制构造
3、要注意不要循环引用,那样会造成对象不会被释放

总结
使用shared_ptr开始提到的问题就迎刃而解了,将里层的map使用类封装,在析构函数中释放里层map的内存,这个类被shared_ptr封装后,就不用担心在第二段被调用时被释放的问题了,最后map变成以下的形式hashmap<key, shared_ptr<class(map<key,value>)>>,细节不再敖述。

引用

http://www.cppblog.com/Solstice/archive/2013/01/28/197597.html
http://www.cnblogs.com/welkinwalker/archive/2011/10/20/2218804.html
http://www.cnblogs.com/TianFang/archive/2008/09/19/1294521.html
http://blog.csdn.net/sndaxdrs/article/details/6175701
http://www.cplusplus.com/reference/memory/shared_ptr/


展开阅读全文

没有更多推荐了,返回首页