auto_ptr C++11已弃用
编译阶段显示没问题
运行阶段会报错
简单分析
对比一下,执行26行代码之后,智能指针baoma此时已经为空指针,再执行第27行代码肯定会报错(引用非法内存的指针)。
这是因为
- auto_ptr要求其对“裸”指针(这里指car)的完全占有性。也就是说一个”裸“指针不能同时被两个以上的auto_ptr所拥有。
- 那么,在拷贝构造或赋值操作时,我们必须作特殊的处理来保证这个特性。auto_ptr的做法是“所有权转移”,即拷贝或赋值的源对象(这里指baoma)将失去对“裸”指针的所有权。
auto_ptr在构造时获取对某个对象的所有权(ownership),在析构时释放该对象。我们可以这样使用auto_ptr来提高代码安全性,从此我们不必关心应该何时释放p,也不用担心发生异常会有内存泄漏。
因为auto_ptr析构的时候肯定会删除他所拥有的那个对象,因此两个auto_ptr不能同时拥有同一个对象。像这样:
int* p = new int(0);
auto_ptr p1( p) ;
auto_ptrp2( p);// 危险!!p将会被释放两次
auto_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是一个类模板
,_Ty是传入参数的类型。
在13行是它的一个拷贝构造函数,在执行代码auto_ptr baoma2(baoma);的时候会调用该构造函数,在该函数中调用了release这个函数。_Right是baoma,_Myptr是baoma2。
在release函数中,转移了裸指针的所有权。使用了一个临时的指针变量_Tmp来接收“裸指针”(car),然后把裸指针赋为0(说明是空指针,不指向任何对象)。也就是说,在执行代码auto_ptr baoma2(baoma);之后,智能指针baoma对裸指针的所有权转移给了baoma2,此时baoma是个空指针。
所以在后面调用27行代码时,重载运算符*,发现_Myptr=0,然后报错。
所以,因为auto_ptr的拷贝构造函数,将裸指针先赋值给目标指针,然后就会释放自身,会导致程序崩溃,是非常危险的。
所以,在C++11中引入了unique_ptr智能指针,用于替代不安全的auto_ptr。