share_ptr 的 知识梳理

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~

猜你喜欢

转载自blog.csdn.net/zhaohuappc/article/details/71643673