65.9K
CodeProject 正在变化。 阅读更多。
Home

共享指针

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.65/5 (7投票s)

2008 年 5 月 19 日

CPOL

2分钟阅读

viewsIcon

25428

downloadIcon

113

共享指针的实现

简介

智能指针是存储指向动态分配(堆)对象的指针的类。它们的行为与内置 C++ 指针非常相似,不同之处在于它们会在适当的时候自动删除指向的对象。智能指针在处理异常时特别有用,因为它们可以确保动态分配的对象被正确销毁。它们还可以用于跟踪由多个所有者共享的动态分配的对象。

实现智能指针的最重要技术之一是使用引用计数方法。你们中的许多人已经编写了自己的智能指针,并且有很多文献讨论了引用计数中涉及的问题。一个重要的细节是如何实现引用计数——侵入式,这意味着你需要在被引用计数的类中添加支持,或者非侵入式,这意味着你不需要。我的实现是非侵入式的,并且使用一个简单的整数引用计数器。

background

你必须了解 C++ 参数传递的基本概念才能理解引用计数机制。在 C++ 中,我们有两种类型的参数传递方式

1) 值传递。
2) 引用传递。
在值传递中,会创建被传递的数据类型的临时副本。在引用传递中,会发送被传递参数的地址,以便对传递参数的任何更改都会直接反映到传递参数的状态中。

现在,如果我们把一个用户定义的对象作为参数传递给一个函数,该函数的拷贝构造函数会被调用来创建一个临时对象,该对象在函数返回后立即被销毁。我使用了这个概念来创建共享指针的实现,以实现自动垃圾回收。

使用代码

这是一个共享指针概念的非常简单的实现。我使用了一个模板类,它包装了一个指向引用计数对象的指针。该对象包装了作为模板参数传递的类的指针。

实现非常简单。它有一个解引用运算符,当使用时会返回包装的指针对象。每当共享指针作为参数传递给函数或涉及拷贝构造函数的情况时,其引用计数都会增加。这个引用计数在析构函数中减少,当它达到 0 时,包装的指针会被释放。
:

///////////////////////////////////////////////////////////////////
///this class implements the reference counting mechanism for the
////////////////////////////class.////////////////////////////////
//////////////////////////////////////////////////////////////////
template <class t> class refcounter_impl {
    private:
    int m_counter;
    t* m_obj;
    public:
    void inc_ref_count() 
    {
        ++m_counter; 
    }
    void dec_ref_count()
    {
        --m_counter;
        if(m_counter<=0)
        {
           destroy_ref();
        }
    }
    t * get_ptr() const
    {
        return ((t *)this);
    }
    void destroy_ref() 
    { 
        if(get_ptr()!=null)
            delete get_ptr();
    }    
    const t& operator=(const refcounter_impl<t>& ref)
    {
        this->m_obj = ref.m_obj;
        m_counter = ref.m_counter;
        inc_ref_count();
    }
    refcounter_impl(t* obj):m_counter(0),m_obj(obj){}
    refcounter_impl(const refcounter_impl<t>& ref)
    {
        this->m_obj = ref.m_obj;
        m_counter = ref.m_counter;
        inc_ref_count();
    }
    
}; 
 
//this is the shared_ptr implementation of the class template 
<class t>
class shared_ptr
{
private:
    refcounter_impl<t>* m_refcounted_obj;    
    void assign(void *ptr)
    {
        if(ptr==null)
            assign((refcounter_impl<t> *)null);
        else
        {
            assign(new refcounter_impl<t>(static_cast<t *>(ptr)));
        }
    }
    void assign(refcounter_impl<t> *refcount)
    {                
        if(refcount!=null)
            refcount->inc_ref_count();
        m_refcounted_obj = refcount;        
    }
public:        
    shared_ptr() :m_refcounted_obj(null){}
    shared_ptr(t* obj) :m_refcounted_obj(null)
    {
        assign(obj);
    }
    shared_ptr(const shared_ptr& ref)
    {        
        assign(ref.m_refcounted_obj);
    }
    shared_ptr& operator=(const shared_ptr& ref)
    {
        assign(ref.m_refcounted_obj);
        return *this;
    }
    t* operator->()
    {
        if(m_refcounted_obj)
            return m_refcounted_obj->get_ptr();
        else
            return null;
    }
    ~shared_ptr()
    {
        m_refcounted_obj->dec_ref_count();
    }

}; 

结论

  • 这是一个共享指针技术的非常简单的实现,我特意保持了它的简单,以便中级用户理解。高级用户可能不会参考这篇文章,但对于具有 2-3 年开发经验并开始实现更大规模项目的人来说,它将非常有帮助。

值得关注的点

  • 我特别喜欢在编写这篇文章时探索 C++ 参数传递机制。
  • 你可以下载 concepts.zip 文件夹来查看完整的 C++ 代码以及我的实现示例。
© . All rights reserved.