auto_ptr简介
auto_ptr一个对象只有一个拥有者(一个萝卜一个坑,两个auto_ptr不能同时拥有同一个对象)
注:
对于智能指针可以参看《Beyond the C++ Standard Library:An Introduction to Boost》、
《boost_1_41_0_doc》地址:http://code.google.com/p/boost-doc-zh/ ,都很给力
在c++11标准中auto_ptr被废弃了。。引入了shared_ptr和unique_ptr不过还是在很多的场所可以使用,先来看一看
auto_ptr的设计动机
1.程序忘记释放申请的资源2.异常而没有正确释放申请的资源
eg:
//一般版本
void fun()
{
try
{
T *ptr = new T;
......
}catch(...)
{
delete ptr;
throw;
}
delete ptr;
}
//auto_ptr版本
void fun()
{
auto_ptr<T> ptr(new T);
......
}
//From vs2010 memory//
// include auto_ptr shared_ptr weak_ptr unique_ptr in vs2010
//
// TEMPLATE CLASS auto_ptr
template<class _Ty>
class auto_ptr;
template<class _Ty>
struct auto_ptr_ref
{ // proxy reference for auto_ptr copying 使我们可以拷贝和赋值临时的右值auto_ptr,在下面的auto_ptr构造函数中使用
explicit auto_ptr_ref(_Ty *_Right)
: _Ref(_Right)
{ // construct from generic pointer to auto_ptr ptr
}
_Ty *_Ref; // generic pointer to auto_ptr ptr
};
template<class _Ty>
class auto_ptr
{ // wrap an object pointer to ensure destruction
public:
typedef auto_ptr<_Ty> _Myt;
typedef _Ty element_type;
explicit auto_ptr(_Ty *_Ptr = 0) _THROW0()
: _Myptr(_Ptr)
{ // construct from object pointer
}
auto_ptr(_Myt& _Right) _THROW0()
: _Myptr(_Right.release())
{ // construct by assuming pointer from _Right auto_ptr
}
auto_ptr(auto_ptr_ref<_Ty> _Right) _THROW0()
{ // construct by assuming pointer from _Right auto_ptr_ref
_Ty *_Ptr = _Right._Ref;
_Right._Ref = 0; // release old
_Myptr = _Ptr; // reset this
}
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_ref
_Other *_Cvtptr = _Myptr; // test implicit conversion
auto_ptr_ref<_Other> _Ans(_Cvtptr);
_Myptr = 0; // pass ownership to auto_ptr_ref
return (_Ans);
}
template<class _Other>
_Myt& 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
}
_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);
}
~auto_ptr()
{ // destroy the object
delete _Myptr;
}
_Ty& operator*() const _THROW0()
{ // return designated value
#if _ITERATOR_DEBUG_LEVEL == 2
if (_Myptr == 0)
_DEBUG_ERROR("auto_ptr not dereferencable");
#endif /* _ITERATOR_DEBUG_LEVEL == 2 */
return (*get());
}
_Ty *operator->() const _THROW0()
{ // return pointer to class object
#if _ITERATOR_DEBUG_LEVEL == 2
if (_Myptr == 0)
_DEBUG_ERROR("auto_ptr not dereferencable");
#endif /* _ITERATOR_DEBUG_LEVEL == 2 */
return (get());
}
_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
};
auto_ptr复制控制函数的特点
auto_ptr的复制构造函数和赋值操作符都很bt,会把所有权挪给新对象,同时原对象置为0,详见上面的源码
eg:
//只能使用显式构造函数,因为auto_ptr_ref使得临时对象可以被构造
//通过auto_ptr(auto_ptr_ref<_Ty> _Right) _THROW0()把auto_ptr<int>(new int(0))转换成auto_ptr_ref<T>
//发现类型转换函数operator auto_ptr_ref<Y>() throw()从而转换成auto_ptr<int>
auto_ptr<int> pi1(new int(100));
auto_ptr<int> pi2(pi1);//pi1的所有权给了pi2,pi1为nullptr,pi2现在当然于pi1了,但不能对pi1解引用了
//auto_ptr<int> pi2=pi1;
auto_ptr的使用规则
1.auto_ptr不能指向数组,因为在auto_ptr中析构函数用的是delete而不是delete[],详见源码2.auto_ptr不能被用在stl标准容器中,auto_ptr不具有值语义(比如== !=),因为源码中都没有重载这些操作符
3.较为隐蔽的情形:
将auto_ptr作为函数参数按值传递,因为在函数调用过程中在函数的作用域中会产生一个局部对象来接收传入的auto_ptr拷贝构造,这样,传入的实参auto_ptr就失去了其对原对象的所有权,而该对象会在函数退出时被局部auto_ptr删除。
eg:
void f(auto_ptr<int> ap){cout<<*ap;}
auto_ptr<int> ap1(new int(0));
f(ap1);
cout<<*ap1; //错误,经过f(ap1)函数调用,ap1已经不再拥有任何对象了