下面的代码是我在看了ubuntu16.04系统默认自带的stl源码后整理的shared_ptr和weak_ptr代码简洁版,为了容易理解去掉了一些基类,函数以及对多线程等情况的处理,对变量名和函数名也做了修改。
// counted_ptr只能通过new在堆上构造,而不在栈上构造。
template<typename Ptr>
class counted_ptr {
public:
explicit counted_ptr(Ptr p):ptr(p), use_count(1), weak_count(1) {}
// 资源的释放由函数dispose负责,所以析构函数不需要任何操作
~counted_ptr() {}
// 增加计数(use_count)
void add_ref_copy() {++use_count;}
// 从weak_ptr转化为shared_ptr时候需要调用,
// 因为weak_ptr并不会增加计数(use_count),
// 所以weak_ptr指向的资源可能已经被释放
void add_ref_lock() {
if(use_count == 0)
THROW_BAD_WEAK_PTR;
++use_count;
}
// 每增加一个weak_ptr,weak_count计数加一
void weak_add_ref() {++weak_count;}
// 当weak_count为0的时候,说明既不存在shared_ptr也不存在weak_ptr
// 对象在管理ptr指向的资源,所以该计数对象(*this)也可以释放了
// (ptr指向的资源在最后一个shared_ptr对象析构的时候已经被释放了)。
void weak_release() {
if(--weak_count == 0)
destroy();
}
int get_use_count() const {return use_count;}
void dispose() {delete ptr;} //(use_count)计数变为0,释放掉所管理的资源
void destroy() {delete this;} // 释放计数对象本身(会调用析构函数)
// 每个shared_ptr对象析构的时候都要调用该函数
// 在最后一个shared_ptr对象析构时(use_count变为0)释放ptr指向的资源
// 如果weak_count也变为0,说明也不存在weak_ptr对象了,所以计数对象本身也可以释放了
void relase() {
if(--use_count == 0) {
dispose();
if(--weak_count == 0)
destroy();
}
}
private:
// 禁止复制
counted_ptr(const counted_ptr&) = delete;
counted_ptr& operator=(const counted_ptr&) = delete;
int use_count; // 负责管理ptr指向资源的shared_ptr对象的个数
// 还在使用该计数对象(*this,而不是ptr指向的资源)的weak_ptr对象个数,如果至
// 少存在一个也在使用该count_ptr对象则再加1。如果weak_count变为0,则说明既没有
// weak_ptr也不没有shared_ptr在使用该计数对象,则可以释放掉该计数对象;如果
// use_count=0而weak_count!=0则ptr指向的资源已被释放,但还存在weak_ptr在使用
// 该计数对象,所以还不能释放该计数对象。
int weak_count;
Ptr ptr;
};
// 向前声明,所以可以在shared_count内使用weak_count
template <typename Ptr> class weak_count;
template <typename Ptr>
class shared_count {
public:
constexpr shared_count(): pi(0) {}
explicit shared_count(Ptr p): pi(0) {
try {
pi = new counted_ptr(p);
}
catch(...) {
delete p;
throw;
}
}
shared_count(const shared_count& r): pi(r.pi) {
if(pi != 0)
pi->add_ref_copy();
}
// 由weak_ptr得到shared_ptr,需要检查所管理的资源释放已经被释放,
// 如果没有被释放,则增加计数
shared_count(const weak_count& r): pi(r.pi) {
if(pi != nullptr)
pi->add_ref_lock();
}
shared_count& operator=(const shared_count& r) {
counted_ptr tmp = r.pi;
if(tmp != pi) {
if(tmp != 0)
tmp->add_ref_copy(); // 增加r所管理的资源的计数
if(pi != 0)
pi->release(); // 使原来资源的计数减一,如果减一后变为0还需要释放掉资源
pi = tmp;
}
return *this;
}
~shared_count() {
if(pi != nullptr)
pi->release();
}
void swap(shared_count& r) {
counted_ptr* tmp = r.pi;
r.pi = pi;
pi = tmp;
}
int get_use_count() const {
return pi != 0 ? pi->get_use_count() : 0;
}
bool unique() const {
return this->get_use_count() == 1;
}
private:
friend class weak_count;
counted_ptr* pi;
};
template <typename Ptr> class shared_count; //同上
template <typename Ptr>
class weak_count {
public:
constexpr weak_count(): pi(nullptr) {}
weak_count(const shared_count& r): pi(r.pi) {
if(pi != nullptr)
pi->weak_add_ref();
}
weak_count(const weak_count& r): pi(r.pi) {
if(pi != nullptr)
pi->weak_add_ref();
}
weak_count(weak_count&& r): pi(r.pi) {
r.pi = nullptr;
}
~weak_count() {
if(pi != nullptr)
pi->weak_release();
}
weak_count& operator=(const shared_count& r) {
counted_ptr* tmp = r.pi;
if(tmp != nullptr)
tmp->weak_add_ref();
if(pi != nullptr)
pi->weak_release();
pi = tmp;
return *this;
}
weak_count& operator=(const weak_count& r) {
counted_ptr* tmp = r.pi;
if(tmp != nullptr)
tmp->weak_add_ref();
if(pi != nullptr)
pi->weak_release();
pi = tmp;
return *this;
}
weak_count& operator=(weak_count&& r) {
if(pi != nullptr)
pi->weak_release();
pi = r.pi;
r.pi = nullptr;
return *this;
}
void swap(weak_count& r) {
tmp = r.pi;
r.pi = pi;
pi = tmp;
}
int get_use_count() const {
return pi != nullptr ? pi->get_use_count() : 0;
}
private:
friend class shared_count;
counted_ptr* pi;
};
template <typename T> class weak_ptr;
template <typename T>
class shared_ptr {
public:
constexpr shared_ptr(): ptr(0), refcount() {}
constexpr shared_ptr(nullptr):shared_ptr() {}
explicit shared_ptr(T* p): ptr(p), refcount(p) {}
shared_ptr(const shared_ptr&) = default;
shared_ptr(shared_ptr&& r):ptr(r.ptr), refcount() {
refcount.swap(r.refcount);
r.ptr = 0;
}
shared_ptr(const weak_ptr& r): refcount(r.refcount) {
ptr = r.ptr;
}
shared_ptr& operator=(const shared_ptr&) = default;
shared_ptr& operator=(shared_ptr&& r) {
shared_ptr(std::move(r)).swap(*this);
return *this;
}
~shared_ptr() = default;
void reset() {
shared_ptr().swap(*this);
}
void reset(T* p) {
assert(p == 0 || p != ptr);
shared_ptr(p).swap(*this);
}
T& operatpr*() const {
assert(ptr != 0);
return *ptr;
}
T* operator->() const {
assert(ptr != 0);
return ptr;
}
T* get() const {return ptr;}
bool unique() const {return refcount.unique();}
int use_count() const { return refcount.get_use_count();}
explicit operator bool() const {return ptr == 0;}
void swap(shared_ptr& other) {
std::swap(ptr, other.ptr);
refcount.swap(other.refcount);
}
private:
friend class weak_ptr;
T* ptr;
// shared_count通过counted_ptr来间接管理ptr指向资源
shared_count refcount;
};
template <typename T> class shared_ptr;
template <typename T>
class weak_ptr {
public:
constexpr weak_ptr(): ptr(nullptr), refcount() {}
weak_ptr(const weak_ptr&) = default;
weak_ptr(weak_ptr&& r): ptr(r.ptr), refcount(std::move(r.refcount)) {
r.ptr = nullptr;
}
weak_ptr(const shared_ptr& r): ptr(r.ptr), refcount(r.refcount) {}
~weak_ptr() = default; // 会自动调用weak_count的析构函数
weak_ptr& operator=(const weak_ptr& r) = default;
weak_ptr& operator=(const shared_ptr& r) {
ptr = r.ptr;
// 调用weak_count的operator=(const shared_count&)函数
refcount = r.refcount;
return *this;
}
weak_ptr& operator=(weak_ptr&& r) {
ptr = r.ptr;
refcount = std::move(r.refcount);
r.ptr = nullptr;
return *this;
}
shared_ptr lock() const {
// 间接利用构造函数shared_count(const weak_count&)检查资源是否已被释放
return shared_ptr(*this);
}
int use_count() const { return refcount.get_use_count();}
bool expired() const {return refcount.get_use_count() == 0;}
void reset() {
weak_ptr().swap(*this);
}
void swap(weak_ptr& s) {
std::swap(ptr, s.ptr);
refcount.swap(s.refcount);
}
private:
friend class shared_ptr;
T* ptr;
weak_count refcount;
};