shared_ptr,weak_ptr源码解析
来源:互联网 发布:精通matlab混合编程 编辑:程序博客网 时间:2024/05/16 10:10
下面的代码是我在看了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_counttemplate <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;};
0 0
- shared_ptr,weak_ptr源码解析
- boost shared_ptr 源码解析
- C++ 智能指针(shared_ptr/weak_ptr)源码分析
- enable_shared_from_this、weak_ptr、shared_ptr
- auto_ptr,scoped_ptr,shared_ptr,weak_ptr
- weak_ptr,shared_ptr,scoped_ptr
- auto_ptr,shared_ptr,weak_ptr,scoped_ptr
- 智能指针--shared_ptr&&weak_ptr
- shared_ptr or weak_ptr
- weak_ptr与shared_ptr
- shared_ptr,weak_ptr,unique_ptr
- weak_ptr和shared_ptr,以及什么时候用weak_ptr
- boost之shared_ptr,weak_ptr计数
- 简单实现auto_ptr,shared_ptr,weak_ptr
- auto_ptr scoped_ptr scoped_array shared_ptr weak_ptr
- auto_ptr,scoped_ptr,shared_ptr,weak_ptr区别
- std::shared_ptr 和 std::weak_ptr
- shared_ptr 之循环引用 weak_ptr
- 《Training:Adding an Easy Share Action》
- activity切换动画
- 【机器学习(李宏毅)】四、Gradient Descent
- pl/sql 数据修改不了问题(表被锁了)
- centos7 mysql数据库安装和配置
- shared_ptr,weak_ptr源码解析
- 面试10之删除非尾节点
- Testng执行顺序控制
- I.T. Professional
- appium之事件监听(二)
- Phoenix二级索引(Secondary Indexing)的使用
- g2o:一种图优化的C++框架
- POJ
- BZOJ4825: [Hnoi2017]单旋