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 So
std::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作为标准容器的元素,因为在某些动作中原有的指针会交出拥有权。