当前位置:编程学习 > C/C++ >>

引用计数的智能指针的实现与思考

引用计数在软件开发中是一项非常重用的技术,它可以说是无处不,我们在不知不觉中都在和它打交道,比如 Windows上的COM和Handle, Mac上的ref句柄,脚本语言中的垃圾回收技术。

但是在C++标准库中,却没有内置支持引用计数的技术的支持,下面我们就尝试封装自己的基于引用计数的智能指针。

一般来说,计数方法的实现有2种,内置和外置: 内置指的是对象本身就有计数功能,也就是计数的值变量是对象的成员;外置则是指对象本身不需要支持计数功能,我们是在外部给它加上这个计数能力的。

首先我们来看内置的方法:
封装一个计数功能的对象CRefObject:
class CRefObject
{
public:
    CRefObject()
    {
        m_nRefCount = 0;
    }

    int GetRefCount() const
    {
        return m_nRefCount;
    }

    int AddRefCount()
    {
        return ++m_nRefCount;
    }

    int SubRefCount()
    {
        return --m_nRefCount;
    }

    void ResetRefCount()
    {
        m_nRefCount = 0;
    }

private:
    int    m_nRefCount;
};

然后封装我们的智能智能CRefPtr<T>:
//T should inherit from CRefObject
template<typename T>
class CRefPtr
{
public:
    T* operator->() const
    {
        return m_pRawObj;
    }

    T& operator()() const
    {
        assert(m_pRawObj != NULL);
        return *m_pRawObj;
    }

    T& operator*() const
    {
        assert(m_pRawObj != NULL);
        return *m_pRawObj;
    }

    T* GetPtr() const
    {
        return m_pRawObj;
    }

    bool IsNull() const
    {
        return m_pRawObj == NULL;
    }

    explicit CRefPtr(T* p = NULL)
    {
        m_pRawObj = p;
        if(p != NULL)
        {
            p->AddRefCount();
        }
    }

    CRefPtr(const CRefPtr& ref)
    {
        m_pRawObj = ref.m_pRawObj;
        if(m_pRawObj != NULL)
        {
            m_pRawObj->AddRefCount();
        }
    }

    ~CRefPtr()
    {
        if(m_pRawObj != NULL && m_pRawObj->SubRefCount() == 0)
        {
            delete m_pRawObj;
        }
    }

    CRefPtr& operator = (const CRefPtr& ref)
    {
        if(this != &ref)
        {
            if(m_pRawObj != NULL
                && m_pRawObj->SubRefCount() == 0)
            {
                delete m_pRawObj;
            }

            m_pRawObj = ref.m_pRawObj;

            if(m_pRawObj != NULL)
            {
                m_pRawObj->AddRefCount();
            }
        }

        return *this;
    }

    bool operator == (const CRefPtr& ref) const
    {
        return m_pRawObj == ref.m_pRawObj;
    }

private:
    T* m_pRawObj;
};

通过上面的代码可以看到,我们要求要支持引用计数的对象都要从CRefObject继承,也就是给这个对象内置计数功能。

然后我们就可以这样使用了:
#include <iostream>
using namespace std;
#include "RefPtr.h"
class CTest: public CRefObject
{
public:
CTest(int n)
:m_n(n)
{
cout << "CTest(" << m_n << ") \n";
}
~CTest()
{
cout << "~CTest(" << m_n << ") \n";
}
void Print()
{
cout << m_n << "\n";
}
int m_n;
};
int main(int argc, char* argv[])
{
{
CRefPtr<CTest> p1(new CTest(1));
CRefPtr<CTest> p2(new CTest(2));
p1->Print();
p1 = p2;
}
system("pause");
return 0;
}

接下来我们尝试实现据通过外置方法实现引用计数的智能指针CRefIPtr<T>, 代码如下:
template<typename T>
class CRefIPtr
{
public:
    T* operator->() const
    {
        return GetObjectPtr();
    }

    T& operator()() const
    {
        return GetObject();   
    }

    T& operator*() const
    {
        return GetObject();
    }

    T* GetPtr() const
    {
        return GetObjectPtr();
    }

    bool IsNull() const
    {
        return (m_pHolder != NULL
            && m_pHolder->m_pRawObj != NULL);
    }

    explicit CRefIPtr(T* p = NULL)
    {
        m_pHolder = new CRefHolder;

        if(m_pHolder != NULL)
        {
        &n

补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,