share_ptr 的 知识梳理

来源:互联网 发布:全身美白 知乎 编辑:程序博客网 时间:2024/05/16 16:00

share_ptr 的 知识梳理笔记
最近学习share_ptr 的时候发现这是个很有用的智能指针,无论是内存管理还是线程安全,以及自定义删除器, 所以觉得还是记录分享一下,同时也巩固一下自己的学习成果
1,share_ptr 是何物
采用引用计数的智能指针。 shared_ptr基于“引用计数”模型实现,多个shared_ptr可指向同一个动态对象,并维护了一个共享的引用计数器,记录了引用同一对象的shared_ptr实例的数量。当最后一个指向动态对象的shared_ptr销毁时,会自动销毁其所指对象(通过delete操作符)。shared_ptr的默认能力是管理动态内存,但支持自定义的Deleter以实现个性化的资源释放动作。头文件:。
基本操作:shared_ptr的创建、拷贝、绑定对象的变更(reset)、shared_ptr的销毁(手动赋值为nullptr或离开作用域)、指定deleter等操作。
shared_ptr的创建,有两种方式,一,使用函数make_shared(会根据传递的参数调用动态对象的构造函数);二,使用构造函数(可从原生指针、unique_ptr、另一个shared_ptr创建)

shared_ptr<int> p1 = make_shared<int>(1);// 通过make_shared函数  shared_ptr<int> p2(new int(2));// 通过原生指针构造  

此外智能指针若为“空“,即不指向任何对象,则为false,否则为true,可作为条件判断。可以通过两种方式指定deleter,一是构造shared_ptr时,二是使用reset方法时。可以重载的operator->, operator *,以及其他辅助操作如unique()、use_count(), get()等成员方法。

2,shared_ptr的线程安全性
boost官方文档对shared_ptr线程安全性的正式表述是:shared_ptr对象提供与内置类型相同级别的线程安全性。【shared_ptrobjects offer the same level of thread safety as built-in types.】具体是以下三点。

  1. 同一个shared_ptr对象可以被多线程同时读取。【A shared_ptrinstance can be “read” (accessed using only const operations)simultaneously by multiple threads.】

  2. 不同的shared_ptr对象可以被多线程同时修改(即使这些shared_ptr对象管理着同一个对象的指针)。【Different shared_ptr instances can be “written to”(accessed using mutable operations such as operator= or reset) simultaneouslyby multiple threads (even when these instances are copies, and share the samereference count underneath.) 】

  3. 任何其他并发访问的结果都是无定义的。【Any other simultaneous accesses result in undefined behavior.】同一个shared_ptr对象不能被多线程直接修改,但可以通过原子函数完成。
    我简单地理解为,除了多线程直接修改(非原子函数)同一个share_ptr ,其他都是安全的

3,share_ptr 使用中可能碰到的有意思问题,循环引用
“循环引用”简单来说就是:两个对象互相使用一个shared_ptr成员变量指向对方的会造成循环引用。导致引用计数失效。而解决的办法其实是另一个weak_ptr 智能指针的使用,这里具体就不多说了,需要知道的是,weak_ptr不参与引用计数, 两个常用的功能函数:expired()用于检测所管理的对象是否已经释放;lock()用于获取所管理的对象的强引用指针, 譬如

  void doSomthing()      {          shared_ptr<B> pp = pb.lock();          if(pp)//通过lock()方法来判断它所管理的资源是否被释放          {              cout<<"sb use count:"<<pp.use_count()<<endl;          }      }  

4,share_ptr 的自定义删除器
这个直接上代码吧,两个代码片段,看了应该就明白了,不明白的你再多看两遍,呵呵~~

#include <iostream>#include <memory>struct dialog_t { };template<class T>struct deleter_t{ void operator () (T* x) const {  if(x != NULL )  {   std::cout << __LINE__ << std::endl;   delete x;   x=NULL;  } }};int main (){ auto const p = std::shared_ptr<dialog_t>(new dialog_t, deleter_t<dialog_t>{});}

分割开,上面这个就是个单独的代码片,下面的是有测试用例的

template<class T>//注意这里有模版  struct Del  {      void operator()(const T* ptr)      {          delete ptr;      }  };  struct Free//注意这里没有模版  {      void operator()(void* ptr)      {          free(ptr);      }  };  struct Fclose  {      void operator()(FILE* ptr)      {          fclose(ptr);      }  };  template<class T,class Deleter=Del<T>>  class SharedPtr  {  public:      SharedPtr(T* ptr, Deleter del)          :_ptr(ptr)          , _pCount(new long(1))          , _del(del)      {}      SharedPtr(T* ptr)          :_ptr(ptr)          , _pCount(new long(1))      {}      ~SharedPtr()      {          _Release();      }  protected:      void _Release()      {          if (--*_pCount == 0)          {              _del(_ptr);              delete _pCount;          }      }  private:      T* _ptr;      long* _pCount;      Deleter _del;  };  

测试用例

void Test()  {      SharedPtr<int>sp1(new int(1));      SharedPtr<int,Free>sp2((int*)malloc(sizeof(int) * 10), Free());//注意怎么调用的  }  

先到这里,后面还有的话再补上,当然可爱的你也可以在评论里直接追加,3q~

0 0