auto_ptr是std中的一个型别,是“它所指向的对象”的拥有者。auto_ptr是一种智能指针(Smart Poiner)。主要用于防止“在当程序抛出异常的时候,发生资源泄漏”问题的发生。
auto_ptr的表现如是:当auto_ptr的生命周期结束的时候,那么它指向的对象也会被delete。
语法:std::auto_ptr<ClassName> ptr(new ClassName());
需要:#include <memory>
auto_ptr的接口定义得非常好,可以像使用其他指针一样来使用它,因为它提供了operator *和operator ->,operator *可以用来提取指针所指向的对象,而operator ->可以访问指针所指向对象的数据成员。但是auto_ptr并没有给出operator ++的运算,这正是为什么C++的某些使用中更多推荐使用引用,而不是指针的原因了。
注意:不能像使用一般指针一样为Smart Pointer赋值。
Like This:std::auto_ptr<ClassName> ptr(new ClassName()); //OK, Constructor Make It Sostd::auto_ptr<ClassName> ptr = new ClassName(); //Error!
源码:
template <class _Ty>class auto_ptr;
template <class _Ty>struct auto_ptr_ref { // proxy reference for auto_ptr copying auto_ptr_ref(auto_ptr<_Ty>& _Right) : _Ref(_Right) {// construct from compatible auto_ptr } auto_ptr<_Ty>& _Ref; // reference to constructor argument };
template <class _Ty>class auto_ptr {// wrap an object pointer to ensure destruction public: typedef _Ty element_type; explicit auto_ptr(_Ty*_Ptr = 0) _THROW0() : _Myptr(_Ptr) {// construct from object pointer } auto_ptr(auto_ptr<_Ty>& _Right) _THROW0() : _Myptr(_Right.release()) {// construct by assuming pointer from _Right auto_ptr } auto_ptr(auto_ptr_ref<_Ty> _Right) _THROW0() : _Myptr(_Right._Ref.release()) {// construct by assuming pointer from _Right auto_ptr_ref }
template <class _Other> operator auto_ptr<_Other>() _THROW0() { //Convert to Compatible auto_ptr return (auto_ptr<_Other>(*this)); } template <class _Other> operator auto_ptr_ref<_Other>() _THROW0() { //Convert to Compatible auto_ptr_ptr return (auto_ptr_ref<_Other>(*this)); } template <class _Other> auto_ptr<_Ty>& operator = (auto_ptr<_Other>& _Right) _THROW0() {//Assign Compatible _Right(Assume Pointer) reset(_Right.release()); return (*this); }
template <class _Other> auto_ptr(auto_ptr<_Other>& _Right) _THROW0() : _Myptr(_Right.release()) {// construct by assuming pointer from _Right }
template <class _Ty> auto_ptr<_Ty>& operator = (auto_ptr<_Ty>& _Right) _THROW0() { //Assign Compatible _Right(assume pointer) reset(_Right.release()); return (*this); }
template <class _Ty> auto_ptr<_Ty>& operator = (auto_ptr_ref<_Ty>& _Right)_THROW0() {//Assign Compatible _Right._Ref(assume pointer) reset(_Right._ref.release()); return (*this); }
~auto_ptr() { delete Myptr; } //Destroy The Object.
_Ty& operator*() const _THROW0() {// return designated value return (*_Myptr);
}
_Ty *operator->() const _THROW0() {// return pointer to class object return (&**this);
}
_Ty *get() const _THROW0() {// return wrapped pointer return (_Myptr);
}
_Ty *release() _THROW0() {// return wrapped pointer and give up ownership _Ty *_Tmp = _Myptr; _Myptr = 0; return (_Tmp); }
void reset(_Ty* _Ptr = 0) {// destroy designated object and store new pointer if (_Ptr != _Myptr) delete _Myptr; _Myptr = _Ptr; }
private: _Ty *_Myptr; // the wrapped object pointer
};
//[Code End~]
剖析:1.关于两个运算符的重载operator ->会调用到operator *的重载。return (&**this);看起来很让人费解,是这样的,假设:auto_ptr<ClassName> myPtr(new ClassName());myPtr->member; //Call Like This. or{myPtr->memFunc();}所以:*this == myPtr;**this == *myPtr == *_Myptr //Call operator *&**this == _Myptr
所以你也可以这样修改基类代码,如是修改: _Ty* operator->() const _THROW0() {// return pointer to class object return (&**this); //return (_Myptr); } 这样的修改可能会带来其他的隐含错误,只是现在还没有看出来。
2.关于release()和reset()release()成员函数auto_ptr将会放弃先前所指向的对象(资源)所有权,然后返回那个对象的指针,若没有任何拥有,则返回NULL指针。reset()成员函数默认参数为0;即使不设置参数,或者会使得auto_ptr对象放弃任何对象并删除先前拥有的对象资源。若是传入新的指针(不包括先前拥有的对象指针),auto_ptr会delete先前拥有的对象,并拥有新的对象。若是传入该auto_ptr已经拥有的对象,则调用不会产生任何变化。注意:不要将new[]生成的对象指针数组传入,如果需要使用数组,应该考虑STL的容器们。
3.其析构函数就表明了该智能指针的效用来源auto_ptr对象在析构的时候,也就是其生命周期将尽的时候会自动释放它拥有的对象资源。
注意:auto_ptr作为参数的传参问题以及其他:1.若某个函数是此指针的传递终点,那么auto_ptr,所指的是经过传递得到拥有权的auto_ptr,它将会在函数返回的时候被删除,就是在退栈的时候,它的拥有也被删除了。2.作为某一个函数的返回值的时候,auto_ptr被传递给到一个新的函数中,它的历程就刚刚开始了。3.即使有异常被抛出,auto_ptr也会尽职地删除它拥有的数据。4.不要把auto_ptr作为标准容器的元素,因为在某些动作中原有的指针会交出拥有权。