C++ auto_ptr笔记

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。

猜你喜欢

转载自blog.csdn.net/qq_41363459/article/details/114994413