The source code analysis of intelligent pointer

Previous: https://blog.csdn.net/qq_41345173/article/details/104277055
Source code sharing of BOOST library, baidu online disk extraction code: snuc

Article directory

1. introduction

In fact, the internal structure of shared array and shared PTR is the same, except that shared array can be used to directly manage dynamic arrays, making it as convenient as ordinary pointers. Looking at the private members of their source code, they will also find that they have the same structure as the shared_ptr:

private:
    ...
    T * px;                     // contained pointer
    detail::shared_count pn;    // reference counter

2. Definition and use of delegator in smart pointer array series

First, construct a simple remover by imitating the source code, which is convenient for the constructor to set the release mode of the objects on the heap.

template<class T> struct check_array_deleter
{
    void operator()(T *x)const
    {
        delete []x;
    }
};
typedef check_array_deleter<T> deleter;

Then we will discuss how the constructor binds the delegator:

    template<class Y>
    explicit shared_array( Y * p ): px( p ), pn( p, deleter() ){}

It turns out that the shared count object will be handed over to the destructor of the derived class of the lower SP count base class. Let's look at the shared count constructor first:

    template<class Y, class D> 
    shared_count( Y * p, D d ): pi_(new sp_counted_impl_pd<Y, D>(p, d)){}

As mentioned above, let's look at the call logic of this derived class sp ﹣ counted ﹣ impl ﹣ PD:

template<class P, class D> class sp_counted_impl_pd: public sp_counted_base
{
private:
    P* ptr; // In short, it is the object of management
    D del; // This is the eraser
public:
    sp_counted_impl_pd( P *p, D & d ): ptr( p ), del( d ){}
    virtual void dispose() // nothrow
    {
        del( ptr ); //In this way, when the dispose function is called, the remover we defined will be called
    }

So far and very clear about the original and logic of reference counting and management, so the smart pointer design is ingenious because it encapsulates the reference counting class to facilitate the coding implementation. The shared count class is a unified external interface, which can handle all kinds of types, including type conversion, etc., while the next layer is a subclass of SP 65123; counted ﹣ base class, which is public It inherits the SP ﹣ counted ﹣ base class, which contains the count variable use ﹣ count ﹣ as well as the supervised objects and some function interfaces. The above is the discussion of the shared array class.

3. Write your own shared array following the boost library

#include <iostream>
#include <memory>
#include <string>
using namespace std;

template<class T> struct check_array_deleter
{
    void operator()(T *x)const
    {
        delete []x;
    }
};

class sp_counted_base
{
private:
    long use_count_;

public:
    sp_counted_base():use_count_(1){}
    virtual ~sp_counted_base(){
        cout<<"destroy sp_counted_base..."<<endl;
    }
    virtual void dispose()=0;
    void release(){
        if(--use_count_==0)
            dispose();
    }
};

template<class T, class D> class sp_counted_impl_pd:public sp_counted_base
{
private:
    T *x;
    D del;
public:
    sp_counted_impl_pd(T *p, D &d):x(p),del(d){}
    virtual ~sp_counted_impl_pd(){
        cout<<"destroy sp_counted_impl_pd..."<<endl;
    }
    void dispose(){
        if(x)
            del(x);
        delete this;
    }
};

class shared_count
{
private:
    sp_counted_base *pi;
public:
    template <class Y, class D>
    shared_count(Y *p, D d):pi(new sp_counted_impl_pd<Y,D>(p,d)){}
    ~shared_count(){
        if(pi!=0)
            pi->release();
        cout<<"destroy shared_count..."<<endl;
    }
};

template<class T> class shared_array
{
public:
    T *px;
    shared_count pn;
	typedef check_array_deleter<T> deleter;
public:
    shared_array(T *p):px(p),pn(p,deleter()){}
    ~shared_array(){
        cout<<"destroy shared_array..."<<endl;
    }
    T & operator[](int index)const{
        return px[index];
    }
};

int main()
{
    int *p = new int[10];
    shared_array<int> pa(p);
    for(int i=0;i<10;++i)
        pa[i] = i;
    for(int i=0;i<10;++i)
        cout<<pa[i]<<' ';
    cout<<endl;
    return 0;
}

The output is as follows:
0 1 2 3 4 5 6 7 8 9
destroy shared_array...
destroy sp_counted_impl_pd...
destroy sp_counted_base...
destroy shared_count...

Published 27 original articles, won praise 6, visited 3868
Private letter follow

Posted on Wed, 12 Feb 2020 03:44:16 -0500 by bender