智能指针的发展
来源:互联网 发布:点歌软件电脑 编辑:程序博客网 时间:2024/06/05 17:11
通常是经由类模板来实现。借由模板来达成泛型,通常借由类的析构函数来达成自动释放指针所指向的内存或对象。
智能指针的最初动机是使得下面的代码更安全,最初使用
void foo(){ Type* ptr = new Type[10]; // 对p指向的内存块进行赋值 do_something(); delete[] ptr;}
当上面的foo()函数出现异常时:
void foo(){ MyClass* p; try { p = new MyClass; p->DoSomething(); delete p; } catch (...) { delete p; throw; }}
当程序代码越来越长时,程序代码会显得臃肿不堪
auto_ptr:
在使用auto_ptr时,须十分注意资源所有权的概念。auto_ptr是现在标准库里面一个轻量级的智能指针的实现,存在于头文件 memory中,之所以说它是轻量级,是因为它只有一个成员变量(拥有对象的指针),相关的调用开销也非常小。
当有了智能指针时我们可以将上面的代码进行如下改写:
void foo(){ auto_ptr<MyClass> p(new MyClass); p->DoSomething();}
下面我们来看看auto_ptr实现了些什么:(以下的auto_ptr的声明摘自ISO/IEC 14882, section 20.4.5:)
namespace std { template <class Y> struct auto_ptr_ref {}; template <class X> class auto_ptr { public: typedef X element_type; // 20.4.5.1 construct/copy/destroy: explicit auto_ptr(X* p =0) throw(); auto_ptr(auto_ptr&) throw(); template <class Y> auto_ptr(auto_ptr<Y>&) throw(); auto_ptr& operator=(auto_ptr&) throw(); template <class Y> auto_ptr& operator=(auto_ptr<Y>&) throw(); auto_ptr& operator=(auto_ptr_ref<X>) throw(); ~auto_ptr() throw(); // 20.4.5.2 members: X& operator*() const throw(); X* operator->() const throw(); X* get() const throw(); X* release() throw(); void reset(X* p =0) throw(); // 20.4.5.3 conversions: auto_ptr(auto_ptr_ref<X>) throw(); template <class Y> operator auto_ptr_ref<Y>() throw(); template <class Y> operator auto_ptr<Y>() throw(); };}
再来看看赋值运算符的重载和拷贝构造的写法:
//拷贝构造auto_ptr(_Myt& _Right) _THROW0() : _Myptr(_Right.release()) {}auto_ptr(auto_ptr_ref<_Ty> _Right) _THROW0() { _Ty *_Ptr = _Right._Ref; _Right._Ref = 0; // release old _Myptr = _Ptr; // reset this }//赋值_Myt& operator=(_Myt& _Right) _THROW0(){ // assign compatible _Right (assume pointer) reset(_Right.release()); return (*this);}_Myt& operator=(auto_ptr_ref<_Ty> _Right) _THROW0(){ // assign compatible _Right._Ref (assume pointer) _Ty *_Ptr = _Right._Ref; _Right._Ref = 0; // release old reset(_Ptr); // set new return (*this);}//release_Ty *release() _THROW0(){ _Ty *_Tmp = _Myptr; _Myptr = 0; return (_Tmp);}
eg1:
MyClass* p(new MyClass); MyClass* q = p; delete p; p->DoSomething(); p = NULL; q->DoSomething();
可以看出:auto_ptr只是简单的把新构造的对象q 指向了p 的内存空间。delete p 之后 p 可能依然指向某块内存(悬挂的)但是却是无效的指针。
eg2:
void main(){ auto_ptr<MyClass> p(new MyClass); auto_ptr<MyClass> q(p);}
eg3:
void main(){ auto_ptr<MyClass> p(new MyClass); auto_ptr<MyClass> q(new MyClass); { q = p; } //恢复对p的操作,就找不到p}
q指向了p的内存,出作用域后先析构q,p指向空然而这时的p已经找不到了,导致p依然指向某块内存,但却是无效的指针。
简洁版auto_ptr:
template <class T>class SmartPtr{public :` SmartPtr(T * ptr = NULL) : _ptr(ptr ) {} ~ SmartPtr() { if (_ptr ) { delete _ptr ; } } SmartPtr(SmartPtr & ap) : _ptr(ap ._ptr) { ap._ptr = 0; } SmartPtr& operator =(SmartPtr& ap) { if (this != &ap) { _ptr = ap ._ptr; ap._ptr = 0; } return *this ; } T* GetPtr() { return _ptr; } T& operator * () { return *_ptr ; } T* operator -> () { return _ptr ; }private : T* _ptr ;};void Test1 (){ SmartPtr<int > p1 = new int (10); SmartPtr<int > p2 = p1; SmartPtr<int > p3; p3 = p2 ; // *p1 = 4;}
auto_ptr的几点注意事项:
1、auto_ptr不能共享所有权
2、auto_ptr不能指向数组
3、auto_ptr不能作为容器的成员
4、不能通过复制操作来初始化auto_ptr
std::auto_ptr p(new int(42)); //OK
std::atuo_ptrp = new int(42);//Error
这是因为auto_ptr的构造函数被定义了explicit
5、不要把auto_ptr放入容器
对象复制给另一个 auto_ptr p2对象以后,p1则被置空,如果访问p1,则会出现非法访问, auto_ptr 的接口设计存在缺陷!
uniqu-ptr(socped_ptr):
uniqu_ptr的拷贝构造函数和赋值运算符都声明为deleted,也就是说它不能被拷贝,只能通过std::move来转递它所指向的内存的所有权。
std::unique_ptr<int> p1(new int(5));std::unique_ptr<int> p2 = p1; // 编译会出错std::unique_ptr<int> p3 = std::move (p1); // 转移所有权,现在那块内存归p3所有, p1成为无效的指针。p3.reset(); //释放内存。p1.reset(); //实际上什么都没做。std::auto_ptr依然存在,但在C++11中被标为"弃用".
简洁版unique_ptr:
template <class T>class SmartPtr{public : SmartPtr(T * ptr = NULL) : _ptr(ptr ) {} ~ SmartPtr() { if (_ptr ) { delete _ptr ; } } T* GetPtr() { return _ptr ; } T& operator * () { return *_ptr ; } T* operator -> () { return _ptr ; }private : SmartPtr(SmartPtr & ap); SmartPtr& operator =(SmartPtr& ap); //!= //== 拷贝构造 和赋值 不被允许 则这两个也没有意义private : T* _ptr ;};void Test1 (){ SmartPtr<int > p1 = new int (10); //SmartPtr<int> p2 = p1; //SmartPtr<int> p3; //p3 = p2;}
shared_ptr
shared_ptr对象除了包括一个所拥有对象的指针(px)外,还必须包括一个引用计数代理对象(shared_count)的指针(pn)。而这个引用计数代理对象包括一个真正的多态的引用计数对象(sp_counted_base)的指针(_pi),真正的引用计数对象在使用VC编译器的情况下包括一个虚表,一个虚表指针,和两个计数器
shared_ptr完美解决auto_ptr在对象所有权上的局限性(auto_ptr是独占的),在使用引用计数的机制上提供了可以共享所有权的智能指针。
template <class T>class SmartPtr{public : SmartPtr(T* ptr = NULL) : _ptr(ptr ) , _countPtr(new int(1)) {} ~ SmartPtr() { Release(); } SmartPtr(const SmartPtr& ap) : _ptr(ap ._ptr) , _countPtr(ap ._countPtr) { ++ _countPtr[0]; } SmartPtr& operator =(const SmartPtr& ap ) { if (this != &ap) { this->Release (); _ptr = ap ._ptr; _countPtr = ap ._countPtr; ++ _countPtr[0]; } return *this ; } T* GetPtr () { return _ptr ; } int GetCount () { return *_countPtr ; } T& operator * () { return *_ptr ; } T* operator -> () { return _ptr ; }protected : void Release () { if (--_countPtr [0] == 0) { delete _countPtr ; if (_ptr ) { delete _ptr ; } } }private : T* _ptr ; int* _countPtr ;};void Test1 (){ SmartPtr<int > p1 = new int (1); cout<<"p1->count:" <<p1. GetCount()<<endl ; SmartPtr<int > p2 = p1; cout<<"p1->count:" <<p1. GetCount()<<" " ; cout<<"p2->count:" <<p2. GetCount()<<endl ; SmartPtr<int > p3; p3 = p2 ; cout<<"p1->count:" <<p1. GetCount()<<" " ; cout<<"p2->count:" <<p2. GetCount()<<" " ; cout<<"p3->count:" <<p3. GetCount()<<endl ;}
还有shared_array
template <class T>class SmartArrayPtr{public : SmartArrayPtr(T * ptr = NULL) : _ptr(ptr ) , _countPtr(new int(1)) {} ~ SmartArrayPtr() { Release(); } SmartArrayPtr(const SmartArrayPtr& ap) : _ptr(ap ._ptr) , _countPtr(ap ._countPtr) { ++ _countPtr[0]; } SmartArrayPtr& operator =(const SmartArrayPtr& ap) { if (this != &ap) { this->Release (); _ptr = ap ._ptr; _countPtr = ap ._countPtr; ++ _countPtr[0]; } return *this ; } T* GetPtr () { return _ptr ; } int GetCount () { return *_countPtr ; } T& operator [](size_t index) { return _ptr [index]; }protected : void Release () { if (--_countPtr [0] == 0) { delete _countPtr ; if (_ptr ) { delete[] _ptr ; } } }private : T* _ptr ; int* _countPtr ;};void Test2 (){ SmartArrayPtr<int > p1 = new int [20]; cout<<"p1->count:" <<p1. GetCount()<<endl ; SmartArrayPtr<int > p2 = p1; cout<<"p1->count:" <<p1. GetCount()<<" " ; cout<<"p2->count:" <<p2. GetCount()<<endl ; SmartArrayPtr<int > p3; p3 = p2 ; cout<<"p1->count:" <<p1. GetCount()<<" " ; cout<<"p2->count:" <<p2. GetCount()<<" " ; cout<<"p3->count:" <<p3. GetCount()<<endl ; p1[1] = 1; p3[2] = 2; cout<<p1 [1]<<" "<< p1[2]<<endl ;}
- 智能指针的发展
- boost库中智能指针的发展
- 智能指针发展
- 话说智能指针发展之路
- c++:分析智能指针与发展历史
- 智能电视行业的发展
- Boost的智能指针
- 智能指针的释放
- 智能指针的释放
- Android的智能指针
- 智能指针的设计
- Android的智能指针
- android的智能指针
- 智能指针的用法
- 智能指针的理解
- 智能指针的初次见面
- Android的智能指针
- 简单的智能指针
- (转载)hive文件存储格式
- APUE------进程关系
- Spinner的添加
- SQL查询优化:如何写出高性能SQL语句
- 合并两个排序的链表
- 智能指针的发展
- 序列化与反序列化---RPC
- vim设置
- node.js 树状菜单递归算法
- css filter滤镜实例分析
- C++第四次作业
- NFS安装笔记
- @JsonInclude
- LinearLayout半透明效果