共享指针






2.65/5 (7投票s)
共享指针的实现
简介
智能指针是存储指向动态分配(堆)对象的指针的类。它们的行为与内置 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++ 代码以及我的实现示例。