下面的代碼是我在看了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<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<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<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<Ptr>;
counted_ptr<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<Ptr>& 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<Ptr>& r) {
counted_ptr<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<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<Ptr>;
counted_ptr<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<T>& 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>;
T* ptr;
// shared_count通過counted_ptr來間接管理ptr指向資源
shared_count<T*> 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<T>& 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<T>& 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<T> lock() const {
// 間接利用構造函數shared_count(const weak_count&)檢查資源是否已被釋放
return shared_ptr<T>(*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>;
T* ptr;
weak_count<T*> refcount;
};