分类:c++| 发布时间:2015-11-14 18:48:00
我们之前介绍的 shared_ptr 是非侵入式智能指针。 非侵入式的意思是说使用 shared_ptr 时我们不用在我们自己的类中记录引用计数。 而侵入式智能指针通常要在我们自己的类中记录引用计数。 在 shared_ptr 中我们需要 new 一个 shared_count 来记录引用计数, 对于有较高性能要求的系统来说,这是一笔不必要的花销。 侵入式智能指针的提出就是为了解决这个问题,通过直接在客户类中记录引用计数, 避免额外的 shared_count 申请与释放。
#include <cassert>
#include <atomic>
namespace MY_DEMO {
template<typename T>
class intrusive_ptr
{
public:
intrusive_ptr(): px_(0) {
}
intrusive_ptr(T *p, bool add_ref = true): px_(p) {
if (px_ && add_ref) T::intrusive_ptr_add_ref(px_);
}
intrusive_ptr(const intrusive_ptr &r): px_(r.px_) {
if (px_) T::intrusive_ptr_add_ref(px_);
}
~intrusive_ptr() {
if (px_ != 0 ) T::intrusive_ptr_release(px_);
}
intrusive_ptr& operator=(const intrusive_ptr &r) {
this_type(r).swap(*this);
return *this;
}
intrusive_ptr& operator=(T *r) {
this_type(r).swap(*this);
return *this;
}
void reset(T *r = 0) {
this_type(r).swap(*this);
}
T* get() const {
return px_;
}
T* detach() {
T *ret = px_;
px_ = 0;
return ret;
}
T& operator*() const {
assert(px_ != 0);
return *px_;
}
T* operator->() const {
assert(px_ != 0);
return px_;
}
private:
typedef intrusive_ptr this_type;
void swap(intrusive_ptr &r) {
T *tmp = px_;
px_ = r.px_;
r.px_ = tmp;
}
private:
T *px_;
};
template<typename T>
class intrusive_ref_counter
{
public:
static void intrusive_ptr_add_ref(T *self) {
if (self)
++self->ref_count_;
}
static void intrusive_ptr_release(T *self) {
if (self && self->ref_count_ > 0 && !--self->ref_count_)
delete self;
}
protected:
intrusive_ref_counter(): ref_count_(0) {
}
std::atomic_int ref_count_;
};
} // namespace MY_DEMO
在我们的实现中,我们规定所有使用 intrusive_ptr 的类需要实现 intrusive_ptr_add_ref 和 intrusive_ptr_release 两个静态成员函数。 当然你也可以直接继承 intrusive_ref_counter 。
我们来写个简单的例子来测试下实现的侵入式智能指针。
#include <string>
#include <iostream>
#include <cassert>
#include <atomic>
// See intrusive_ptr above
using MY_DEMO::intrusive_ptr;
using MY_DEMO::intrusive_ref_counter;
using std::string;
using std::cout;
using std::endl;
class Person: public intrusive_ref_counter<Person>
{
public:
Person(const string &name): name_(name) {
}
void dump() {
cout << "name: " << name_ << endl
<< "ref_count_: " << ref_count_ << endl;
}
private:
string name_;
};
void test_intrusive_ptr()
{
intrusive_ptr<Person> p(new Person("Jim"));
p->dump();
{
intrusive_ptr<Person> p2(p);
p->dump();
}
cout << "after p2 destruct" << endl;
p->dump();
{
intrusive_ptr<Person> p3;
p3 = p;
p->dump();
}
cout << "after p3 destruct" << endl;
p->dump();
}
输出为:
name: Jim
ref_count_: 1
name: Jim
ref_count_: 2
after p2 destruct
name: Jim
ref_count_: 1
name: Jim
ref_count_: 2
after p3 destruct
name: Jim
ref_count_: 1
可以看到可以正常工作。