C++通用引用计数类/句柄类/指针类【智能指针(share_ptr)、右值引用】————附带详细代码

0 背景

在C++2.0中其实很多地方都用到了这种思想,如智能指针(share_ptr)、右值引用等。它实际上就是一个模版指针类,封装了指向类的指针,当进行赋值操作时,是拷贝一个新对象赋值或者是指向同一个对象。在指向同一个对象时,为了防止对象被还有指向该对象的指针就被删除,设置引用计数,当指向的对象的指针需要修改该对象,而其他指针不需要使用到修改的对象时,可以拷贝一个新的对象,让修改的指针指向。

这个类的好处在于可以避免大量不必要的内存管理和数据复制,提高了程序运行效率。

1 讲解

1.1 浅层拷贝句柄类

两个成员变量,指向对象的指针,引用计数的指针

template <typename T>
class ReferenceHandle{
private:
    T* m_p;
    std::size_t* m_refptr;
};

构造函数:

	//对象指针指向空指针,引用计数设置为1
    ReferenceHandle():m_p(nullptr),m_refptr(new std::size_t(1)){}
    //对象指针指向对象,引用计数设置为1
   ReferenceHandle(T* t):m_p(t),m_refptr(new std::size_t(1)){}

拷贝构造函数:

	//对象指针指向同一个对象,引用计数加1
    ReferenceHandle(const ReferenceHandle& h):m_p(nullptr),m_refptr(h.refptr){
        ++*m_refptr;
    }

赋值构造函数:

//为了防止自我赋值时,
//还没有赋值就提前把对象删除了,这里采取了先对对象引用计数+1
    ReferenceHandle&operator=(const ReferenceHandle& h){
        ++*m_refptr;
        if(--*m_refptr==0){
            delete m_refptr;
            delete m_p;
        }
        m_refptr = h.m_refptr;
        m_p = h.m_p;
        return *this;
    }

析构函数:

//如果引用计数为0,则删除指向的对象和引用计数对象
    ~ReferenceHandle(){
        if(--*m_refptr==0){
            delete m_p;
            delete m_refptr;
        }
    }

bool运算符函数:

//如果指针与实际对象关联,则会返回true,否则返回false
    operator bool() const{ return  m_p;}

operator*和operator->操作赋函数:

//用于访问指针指向的对象
    T&operator*()const {
        if(m_p) return *m_p;
        throw std::runtime_error("unbound Hanlde");
    }
    T*operator->()const {
        if(m_p) return m_p;
        throw std::runtime_error("unbound Hanlde");
    }

1.2 浅、深层结合句柄类

成员对象:指向对象的指针、引用计数指针

template <typename T>
class Ptr{
private:
    T* m_p;
    std::size_t* m_refptr;
};

拷贝构造函数:

    ReferenceHandle():m_p(nullptr),m_refptr(new std::size_t(1)){}
    ReferenceHandle(T* t):m_p(t),m_refptr(new std::size_t(1)){}
    ReferenceHandle(const ReferenceHandle& h):m_p(nullptr),m_refptr(h.refptr){
        ++*m_refptr;
    }

赋值构造函数:

    ReferenceHandle&operator=(const ReferenceHandle& h){
        ++*m_refptr;
        if(--*m_refptr==0){
            delete m_refptr;
            delete m_p;
        }
        m_refptr = h.m_refptr;
        m_p = h.m_p;
        return *this;
    }

析构函数:

    ~ReferenceHandle(){
        if(--*m_refptr==0){
            delete m_p;
            delete m_refptr;
        }
    }

操作符函数:

    operator bool() const{ return  m_p;}
    T&operator*()const {
        if(m_p) return *m_p;
        throw std::runtime_error("unbound Hanlde");
    }
    T*operator->()const {
        if(m_p) return m_p;
        throw std::runtime_error("unbound Hanlde");
    }

复制拷贝成员函数:
当指向的类是自己创建的类时,使用此函数:

    //当存在会改变引用值的情况时,分配新对象
    void makeUnique(){
        if(*m_refptr != 1){
            --*m_refptr;
            m_refptr = new size_t(1);
            //成员函数版本
            m_p = m_p?m_p->clone():0;
            //全局函数版本
//            m_p = m_p?clone(m_p):0;
        }
    }

复制拷贝非成员函数:
当指向类自己无法修改时,使用此函数(例如指向的对象是vector<char*>):

//非成员函数版本
//特化一个模版来处理成员函数中没有clone()的情况(即没有T::clone())
template <class T>T* clone(const T* tp){
    return tp->clone();
}

template <>
std::vector<char>* clone(const std::vector<char>* vp){
    return new std::vector<char>(*vp);
}

    void makeUnique(){
        if(*m_refptr != 1){
            --*m_refptr;
            m_refptr = new size_t(1);
            //成员函数版本
            m_p = m_p?m_p->clone():0;
            //全局函数版本
//            m_p = m_p?clone(m_p):0;
        }
    }

2 完整代码示例

#include <iostream>
using std::cout; using  std::endl;
#include <vector>
#include <stdexcept>

//浅层拷贝句柄类
template <typename T>
class ReferenceHandle{
public:
    ReferenceHandle():m_p(nullptr),m_refptr(new std::size_t(1)){}
    ReferenceHandle(T* t):m_p(t),m_refptr(new std::size_t(1)){}
    ReferenceHandle(const ReferenceHandle& h):m_p(nullptr),m_refptr(h.refptr){
        ++*m_refptr;
    }
    ReferenceHandle&operator=(const ReferenceHandle& h){
        ++*m_refptr;
        if(--*m_refptr==0){
            delete m_refptr;
            delete m_p;
        }
        m_refptr = h.m_refptr;
        m_p = h.m_p;
        return *this;
    }
    ~ReferenceHandle(){
        if(--*m_refptr==0){
            delete m_p;
            delete m_refptr;
        }
    }
    operator bool() const{ return  m_p;}
    T&operator*()const {
        if(m_p) return *m_p;
        throw std::runtime_error("unbound Hanlde");
    }
    T*operator->()const {
        if(m_p) return m_p;
        throw std::runtime_error("unbound Hanlde");
    }
private:
    T* m_p;
    std::size_t* m_refptr;
};

//非成员函数版本
//特化一个模版来处理成员函数中没有clone()的情况(即没有T::clone())
template <class T>T* clone(const T* tp){
    return tp->clone();
}

template <>
std::vector<char>* clone(const std::vector<char>* vp){
    return new std::vector<char>(*vp);
}
//浅层、深层结合句柄类
template <typename T>
class Ptr{
public:
    //当存在会改变引用值的情况时,分配新对象
    void makeUnique(){
        if(*m_refptr != 1){
            --*m_refptr;
            m_refptr = new size_t(1);
            //成员函数版本
//            m_p = m_p?m_p->clone():0;
            //全局函数版本
            m_p = m_p?clone(m_p):0;
        }
    }

    Ptr():m_p(nullptr),m_refptr(new std::size_t(1)){}
    Ptr(T* t):m_p(t),m_refptr(new std::size_t(1)){}
    Ptr(const Ptr& h):m_p(nullptr),m_refptr(h.m_refptr){
        ++*m_refptr;
    }
    Ptr&operator=(const Ptr& h){
        ++*m_refptr;
        if(--*m_refptr==0){
            delete m_refptr;
            delete m_p;
        }
        m_refptr = h.m_refptr;
        m_p = h.m_p;
        return *this;
    }
    ~Ptr(){
        if(--*m_refptr==0){
            delete m_p;
            delete m_refptr;
        }
    }
    operator bool() const{ return  m_p;}
    T&operator*()const {
        if(m_p) return *m_p;
        throw std::runtime_error("unbound Hanlde");
    }
    T*operator->()const {
        if(m_p) return m_p;
        throw std::runtime_error("unbound Hanlde");
    }
private:
    T* m_p;
    std::size_t* m_refptr;
};

class Core{
    friend class ReferenceHandle<Core>;
    virtual Core* clone(){
        return new Core(*this);
    }

public:
    virtual ~Core(){}
    virtual void test(double d, double d2 = 0){cout<<"test(double d1, double d2=0)"<<endl;}
};

class  Derive :public  Core{
    friend class ReferenceHandle<Core>;
public:
    virtual Derive* clone(){
        return new Derive(*this);
    }
    void test(double d1, double d2){cout<<"test(double d1, double d2)"<<endl;}

    typedef std::vector<char>::size_type  size_type;
    //成员函数版本
    char&operator[](size_t i){
        m_data.makeUnique();
        return (*m_data)[i];
    }
private:
    Ptr<std::vector<char>> m_data;
};


int main(){
//    Handle<Core> c(new Derive);
    std::vector<ReferenceHandle<Core>> handle;
    ReferenceHandle<Core> h, h2;
    h = new Core;
    h2 = h;

    return 0;
}
已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 岁月 设计师:pinMode 返回首页