智能指针的发展史
来源:互联网 发布:精灵虚拟光驱激活mac 编辑:程序博客网 时间:2024/06/05 20:25
1 .智能指针的发展史
智能指针的发展要从RAII说起,RAII要求,资源的有效期与持有资源的对象的生命期严格绑定,即由对象的构造函数完成资源的分配(获取),同时由析构函数完成资源的释放。在这种要求下,只要对象能正确地析构,就不会出现资源泄露问题。
(1)C++98提出auto _Ptr,auto_Ptr的设计是让两个指针指向同一块空间,但是这样会存在释放不当,出现程序崩溃的问题。
(2)在Boost库中设计了Scoped_Ptr,Shared_Ptr,Weak_Ptr这三种只能指针
(3)C++11经过进一步改进设计出了Unique_ptr,shared_ptr,Weak_ptr 这三种智能指针,Unique_ptr与相类似。
2.auto_Ptr/Scoped_Ptr/Shared_ptr/Weak_Ptr的设计思想、缺陷,以及它们各自的模拟实现?
(1) auto_Ptr的简单实现
auto_Ptr的几点注意事项:
auto_Ptr不能共享所有权
auto_Ptr不能指向数组
auto_Ptr不能作为容器的成员
不能通过赋值操作来初始化auto_Ptr
template<class T>class auto_Ptr{public: auto_Ptr(T* ptr) :_ptr(ptr) {} // ap2(ap1) auto_Ptr(auto_Ptr<T>& ap) :_ptr(ap._ptr) { ap._ptr = NULL; } // ap1 = ap2 auto_Ptr<T>& operator=(auto_Ptr<T>& ap) { if (this != &ap) { if (_ptr) delete _ptr; _ptr = ap._ptr; ap._ptr = NULL; } return *this; } ~auto_Ptr() { if (_ptr) { delete _ptr; } } T& operator*() { return *_ptr; } T* operator->() { return _ptr; }protected: T* _ptr; };
可以看到一个很明显的缺陷 当使用了构造函数和拷贝构造函数时,原来的智能指针就失效了,使用权交给了新的智能指针,这种方式叫做管理权转移,任何时候只能有一个对象指向那块区域,当有看、两个指针指向同一块区域时,程序会崩溃
(2)Boost阶段 Boost阶段提出Scoped_Ptr 守卫指针 防拷贝
SharedPtr的提出主要是建立在AutoPtr的基础上,为了防止赋值和拷贝构造,可以用两种方法解决, 其一:只声明不实现
其二:声明成私有,这样,编译时就不会报错。
Scoped_Ptr的模拟实现
template<class T>class Scoped_Ptr{public: Scoped_Ptr(T* ptr) :_ptr(ptr) {} ~Scoped_Ptr() { delete _ptr; } T& operator*() { return *_ptr; } T* operator->() { return _ptr; }private: Scoped_Ptr(const Scoped_Ptr<T>&); Scoped_Ptr<T>& operator=(const Scoped_Ptr<T>&);protected: T* _ptr;};
Shared_Ptr的 简单实现
相对 于AutoPtr,Shared _Ptr 解决了指针共享的所有权问题,Shared_Ptr引入了引用计数,可以被自由的拷贝和赋值。
template<class T, class Del>class Shared_Ptr{public: Shared_Ptr() :_ptr(NULL) ,_refCount(NULL) {} Shared_Ptr(T* ptr = NULL, Del del) :_ptr(ptr) ,_refCount(new int(1)) ,_del(del) {} ~Shared_Ptr() { if (--(*_refCount) == 0) { cout<<"delete"<<endl; delete _ptr; _del(_ptr); delete _refCount; } } Shared_Ptr(const Shared_Ptr<T, Del>& sp) :_ptr(sp._ptr) ,_refCount(sp._refCount) { ++(*_refCount); } sp2 = sp3 Shared_Ptr<T>& operator=(const Shared_Ptr<T>& sp) { if (this != &s) if(_ptr != sp._ptr) { if (--(*_refCount) == 0) { delete _ptr; delete _refCount; } _ptr = sp._ptr; _refCount = sp._refCount; ++(*_refCount); } return *this; } int RefCount() { return *_refCount; } T& operator*() { return *_ptr; } T* operator->() { return _ptr; } T* GetPtr() const { return _ptr; }protected: T* _ptr; int* _refCount; Del _del;};
Shared_ptr会带来循环引用问题。Weakptr 是用来解决Shared_ptr循环引用的缺陷问题,WeakPtr是一个弱指针,weak_ptr 设计的目的是为配合 shared_ptr 而引入的一种智能指针来协助 shared_ptr 工作, 它只可以从一个 shared_ptr 或另一个 weak_ptr 对象构造, 它的构造和析构不会引起引用记数的增加或减少.
WeakPtr的模拟实现
template<class T>class Weak_Ptr{public: Weak_Ptr() :_ptr(NULL) {} Weak_Ptr(const Shared_Ptr<T>& sp) :_ptr(sp.GetPtr()) {} T& operator*() { return *_ptr; } T* operator->() { return _ptr; }protected: T* _ptr;};
虽然通过弱引用指针可以有效的解除循环引用, 但这种方式必须在程序员能预见会出现循环引用的情况下才能使用, 也可以是说这个仅仅是一种编译期的解决方案, 如果程序在运行过程中出
了循环引用, 还是会造成内存泄漏。
循环引用问题
你中有我,我中有你最后都导致双放都无法释放,最终导致内存泄漏,以双链表为例
struct ListNode{ Weak_Ptr<ListNode> _prev; Weak_Ptr<ListNode> _next; ~ListNode() { cout<<"~ListNode()"<<endl; }};void TestCycleRef(){ Shared_Ptr<ListNode> cur = new ListNode; Shared_Ptr<ListNode> next = new ListNode; cur->_next = next; next->_prev = cur;}
在这里,_next和_prev都是成员变量,第一块空间要想释放必须在第二块空间被释放之后才能释放,但由于第一块空间有一个节点指向第二块空间,所以只有第一块空间释放之后第二块空间才能释放,这样就带来了循环引用问题。
- 智能指针的发展史
- 智能穿戴是计算机发展史的一场重大革命
- Boost的智能指针
- 智能指针的释放
- 智能指针的释放
- Android的智能指针
- 智能指针的设计
- Android的智能指针
- android的智能指针
- 智能指针的用法
- 智能指针的理解
- 智能指针的初次见面
- Android的智能指针
- 简单的智能指针
- 智能指针的使用
- andoid的智能指针
- C++的智能指针
- 智能指针的理解
- ubuntu rebar3 安装
- SSH框架的初步搭建
- js数组的迭代器方法(some、every、forEach、map、filter)
- Common sense for server
- bzoj1222 [HNOI2001]产品加工(dp)
- 智能指针的发展史
- L1-004. 计算摄氏温度
- 大数的四则运算之乘法----Java代码实现
- windows C++ 遍历目录,获取文件名和文件路径
- Time To Get Up——个人c++解
- liunx 修改时间
- Linux系统-程序运行CPU核心绑定
- How Many Maos Does the Guanxi Worth (dijkstra)
- 聚簇索引对数据插入的影响