智能指针的模拟实现shared_ptr 循环引用 定置删除器
来源:互联网 发布:windows更新消失 编辑:程序博客网 时间:2024/05/17 23:58
auto_ptr与scoped_ptr的实现见本人的上篇博客。
三、shared_ptr
shared_ptr的实现原理是通过引用计数来实现,只有当引用计数为1时才释放空间,否则只需将引用计数减1.拷贝和赋值将引用计数加1,具体代码如下:
template <typename T>class SharedPtr{public:SharedPtr();SharedPtr(T* ptr);SharedPtr(const SharedPtr<T>& ap);~SharedPtr();//SharedPtr<T>& operator=(const SharedPtr<T>& ptr);//传统写法SharedPtr<T>& operator=(SharedPtr<T> ap);//现代写法T& operator*()const;T* operator->()const;long GetCount()const;T* GetPtr()const;protected:void _Realease();protected:T* _ptr;long* _pCount;};template <typename T>SharedPtr<T>::SharedPtr() :_ptr(NULL), _pCount(new long(1)){}template <typename T>SharedPtr<T>::SharedPtr(T* ptr) : _ptr(ptr), _pCount(new long(1)){}template <typename T>SharedPtr<T>::SharedPtr(const SharedPtr<T>& ap) : _ptr(ap._ptr), _pCount(ap._pCount){++(*this->_pCount);}template <typename T>SharedPtr<T>::~SharedPtr(){this->_Realease();}//template <typename T>//传统写法//SharedPtr<T>& SharedPtr<T>::operator=(const SharedPtr<T>& ap)//{//if (this->_ptr != ap._ptr)//{//this->_Realease();//this->_ptr = ap._ptr;//this->_pCount = ap._pCount;//++(*this->_pCount);//}//return *this;//}template <typename T>//现代写法SharedPtr<T>& SharedPtr<T>::operator=(SharedPtr<T> ap){swap(this->_ptr, ap._ptr);swap(this->_pCount, ap._pCount);return *this;}template <typename T>T& SharedPtr<T>::operator*()const{return *(this->_ptr);}template <typename T>T* SharedPtr<T>::operator->()const{return this->_ptr;}template <typename T>long SharedPtr<T>::GetCount()const{return *(this->_pCount);}template <typename T>T* SharedPtr<T>::GetPtr()const{return this->_ptr;}template <typename T>void SharedPtr<T>::_Realease(){if (--(*this->_pCount) == 0){delete this->_ptr;delete this->_pCount;}}
然而上面用引用计数实现的简化版看起来不错,但却存在以下问题:
1、引用计数更新存在着线程安全
2、循环引用
3、定置删除器,比如要关闭一个文件,用malloc开辟出来的空间,上述代码均会出现问题
问题1的解决需要对改变引用计数时加锁。我们暂时不讨论,一下我们主要看第二个和第三个问题。
循环引用:
比如有以下结构体和主函数:
struct ListNode{shared_ptr<ListNode> _prev; //shared_ptr为库文件中实现的,只需包memory即可使用shared_ptr<ListNode> _next;~ListNode(){cout << "~ListNode()" << endl;}};int main(){shared_ptr<ListNode> prev; //语句1shared_ptr<ListNode> next; //语句2prev->_next = next; //语句3next->_prev = prev; //语句4}
经语句1、2之后prev的引用计数为1,经3、4后为2,但是最后两个对象均不能释放,因为prev的要释放的前提是next释放,而next的释放又依赖于prev的释放。最后就形成了循环引用,谁都是放不了。解决方案如下:
struct ListNode{weak_ptr<ListNode> _prev;weak_ptr<ListNode> _next;~ListNode(){cout << "~ListNode()" << endl;}};
因为weak_ptr(弱引用智能指针)会对引用计数会做特殊处理(上述情况不加1)。
定置删除器和空间分配器(ps:空间分配器的定置特殊场景下才会这样使用)
eg:如果指针是一个指向文件类型的,在析构函数中只需关闭文件即可,而不是释放空间;如果空间是通过,malloc出来的,那么在析构函数中要调用free函数,而不是delete操作符。上述问题通过仿函数就可以解决。具体代码如下:
template <typename T,class Deleter = Del<T>>class SharedPtr{public:SharedPtr(T* ptr);SharedPtr(T* ptr, Deleter del);SharedPtr(const SharedPtr<T, Deleter>& ap);~SharedPtr();//SharedPtr<T, Deleter>& operator=(const SharedPtr<T, Deleter>& ptr);//传统写法//现代写法SharedPtr<T, Deleter>& operator=(SharedPtr<T, Deleter> ap);T& operator*()const;T* operator->()const;long GetCount()const;T* GetPtr()const;protected:void _Realease();protected:T* _ptr;long* _pCount;Deleter _del;};template <typename T, class Deleter = Del<T>>SharedPtr<T, Deleter>::SharedPtr(T* ptr) :_ptr(ptr), _pCount(new long(1)){}template <typename T, class Deleter = Del<T>>SharedPtr<T, Deleter>::SharedPtr(T* ptr, Deleter del) : _ptr(ptr), _pCount(new long(1)), _del(del){}template <typename T, class Deleter = Del<T>>SharedPtr<T, Deleter>::SharedPtr(const SharedPtr<T, Deleter>& ap) : _ptr(ap._ptr), _pCount(ap._pCount), _del(ap._del){++(*this->_pCount);}template <typename T, class Deleter = Del<T>>SharedPtr<T, Deleter>::~SharedPtr(){this->_Realease();}//template <typename T, class Deleter = Del<T>>//传统写法//SharedPtr<T, Deleter>& SharedPtr<T, Deleter>::operator=(SharedPtr<T, Deleter> ap)//{//if (this->_ptr != ap._ptr)//{//this->_Realease();//this->_ptr = ap._ptr;//this->_pCount = ap._pCount;//++(*this->_pCount);//}//return *this;//}template <typename T, class Deleter = Del<T>>//现代写法SharedPtr<T, Deleter>& SharedPtr<T, Deleter>::operator=(SharedPtr<T, Deleter> ap){swap(this->_ptr, ap._ptr);swap(this->_pCount, ap._pCount);swap(this->_del, ap._del);return *this;}template <typename T, class Deleter = Del<T>>T& SharedPtr<T, Deleter>::operator*()const{return *(this->_ptr);}template <typename T, class Deleter = Del<T>>T* SharedPtr<T, Deleter>::operator->()const{return this->_ptr;}template <typename T, class Deleter = Del<T>>long SharedPtr<T, Deleter>::GetCount()const{return *(this->_pCount);}template <typename T, class Deleter = Del<T>>T* SharedPtr<T, Deleter>::GetPtr()const{return this->_ptr;}template <typename T, class Deleter = Del<T>>void SharedPtr<T, Deleter>::_Realease(){if (--(*this->_pCount) == 0){_del(_ptr);delete this->_pCount;}}
0 0
- 智能指针的模拟实现shared_ptr 循环引用 定置删除器
- shared_ptr之循环引用&定置删除器
- boost库智能指针,循环引用,定置删除器详解
- 智能指针(模拟实现auto_ptr,shared_ptr,scooeptr 以及定制删除器c++ 实现)
- 智能指针的模拟实现 auto_ptr scoped_ptr shared_ptr
- shared_ptr基于引用计数智能指针实现
- shared_ptr基于引用计数智能指针实现
- shared_ptr基于引用计数智能指针实现
- 智能指针:模拟实现auto_ptr,scoped_ptr,shared_ptr
- 智能指针shared_ptr的实现
- C++实现智能指针(shared_ptr和unique_ptr)与删除器
- shared_ptr,带引用计数的智能指针
- c++:分析智能指针shared_ptr存在的循环引用的缺陷
- 关于boost 库 shared_ptr 智能指针的循环引用【2013.10.22】
- shared_ptr:定制删除器 和 循环引用
- shared_ptr智能指针的简单实现
- 智能指针shared_ptr 的简单实现
- 模拟实现auto_ptr、scoped_ptr、shared_ptr等智能指针
- 单继承与多继承中的虚函数表和虚函数指针
- Hyper-V Server故障转移群集安装
- C++虚继承中的对象内存布局
- 智能指针的模拟实现 auto_ptr scoped_ptr shared_ptr
- [并查集 树] BZOJ 4551 [Tjoi2016&Heoi2016]树
- 智能指针的模拟实现shared_ptr 循环引用 定置删除器
- 利用栈计算算数表达式的值
- 稀疏矩阵的压缩存储与转置
- (学习笔记)从引用参数谈到左右值
- 大数据的运算加减乘除
- 迷宫问题并求最短路径
- 迷宫问题
- 广义表的相关操作
- 位图