分类:c++| 发布时间:2015-11-01 21:28:00
在上一篇文章中,我们实现了带引用计数的智能指针 shared_ptr 。 现在我们来改进一下实现,使得代码更清晰,并且使其可以支持 weak_ptr (下一篇讲 weak_ptr 的应用场景以及实现)。
#include <algorithm>
namespace MY_DEMO {
template<typename T>
class sp_count
{
public:
sp_count(T *p): p_(p), use_count_(0) {
}
void add_ref_copy() {
++use_count_;
}
void dispose() {
delete p_;
}
void release() {
if (--use_count_ == 0) {
dispose();
delete this;
}
}
private:
int use_count_;
T *p_;
};
template<typename T>
class shared_count
{
public:
explicit shared_count(T *p = 0): pi_(new sp_count<T>(p)) {
}
~shared_count() {
if (pi_ != 0) pi_->release();
}
shared_count(const shared_count &r): pi_(r.pi_) {
if (pi_ != 0) {
pi_->add_ref_copy();
}
}
shared_count& operator=(const shared_count &r) {
sp_count<T> *tmp = r.pi_;
if (pi_ != tmp) {
if (tmp != 0) tmp->add_ref_copy();
if (pi_ != 0) pi_->release();
pi_ = tmp;
}
return *this;
}
void swap(shared_count &r) {
sp_count<T> *tmp = r.pi_;
r.pi_ = pi_;
pi_ = tmp;
}
private:
sp_count<T> *pi_;
};
template<typename T>
class shared_ptr
{
public:
typedef shared_ptr<T> this_type;
explicit shared_ptr(T *p = 0): px_(p), pn_(p) {
}
shared_ptr(const shared_ptr &r): px_(r.px_), pn_(r.pn_) {
}
~shared_ptr() {
}
void reset(T *p) {
if (p == px_)
return;
this_type(p).swap(*this);
}
T* get() {
return px_;
}
void swap(shared_ptr &r) {
std::swap(px_, r.px_);
pn_.swap(r.pn_);
}
shared_ptr& operator= (const shared_ptr<T> &r) {
px_ = r.px_;
pn_ = r.pn_;
return *this;
}
bool operator! () const {
return !px_;
}
T& operator* () const {
return *px_;
}
T* operator-> () const {
return px_;
}
private:
T *px_;
shared_count<T> pn_;
};
} // namespace MY_DEMO
可以看到这个版本的实现中 shared_ptr 变得更清晰,大部分的工作都交给 shared_count 来做了。
实际上,我们通常会在多线程环境使用 shared_ptr。 为了使我们的 shared_ptr 支持多线程,我们需要在对 sp_count 的 use_count_ 操作变成原子操作。 如果你的编译器支持 C++11 只需要将 sp_count 中的
int use_count_;
改为:
std::atomic_int use_count_;
即可,当然别忘了加上头文件 atomic 。
如果你的编译器不支持 C++11 你需要通过操作系统提供的 API 自己实现原子操作的 use_count_ 。 这里就不一一细说了。