好记性不如铅笔头

C && C++, C++ Primer, 编程

C++智能指针笔记:std::auto_ptr

测试类:

class TestCls
{
public:
	string name;
	int x;
	TestCls(string _name):name(_name)
	{
		cout<<"TestCls "<<name.c_str()<<" Constructor Called\n";
	}
	~TestCls()
	 {
		 cout<<"TestCls "<<name.c_str()<<" Destructor Called\n";
	}
};

最简单的使用方法:

void testAutoPtrFunc()
{
	cout<<"enter testAutoPtrFunc\n";
	//这里直接new一个实例,由于使用了auto_ptr,会自动delete。
	std::auto_ptr<TestCls> auptr1(new TestCls("TEST"));
	cout<<"leave testAutoPtrFunc\n";
}

输出:

enter testAutoPtrFunc
TestCls TEST Constructor Called
leave testAutoPtrFunc
TestCls TEST Destructor Called

赋值,复制等逻辑:

void testAutoPtrFunc()
{
	cout<<"enter testAutoPtrFunc\n";
	std::auto_ptr<TestCls> auptr1(new TestCls("TEST"));
	cout<<"auptr1.get():"<<auptr1.get()<<endl;	

//auto_ptr只能有一个有效引用,因此赋值和复制会自动释放当前的引用。
	std::auto_ptr<TestCls> auptr2(auptr1);
	cout<<"auptr1.get():"<<auptr1.get()<<endl;
	cout<<"auptr2.get():"<<auptr2.get()<<endl;

	std::auto_ptr<TestCls> auptr3 = auptr2;
	cout<<"auptr2.get():"<<auptr2.get()<<endl;	
	cout<<"auptr3.get():"<<auptr3.get()<<endl;	

	cout<<"leave testAutoPtrFunc\n";
}

输出:

enter testAutoPtrFunc
TestCls TEST Constructor Called
auptr1.get():0044CBE8
auptr1.get():00000000
auptr2.get():0044CBE8
auptr2.get():00000000
auptr3.get():0044CBE8
leave testAutoPtrFunc
TestCls TEST Destructor Called

常用方法:

void testAutoPtrFunc()
{
	cout<<"enter testAutoPtrFunc\n";

	TestCls *pTest = new TestCls("TEST");
	pTest->x = 10;
	cout<<"x:"<<pTest->x<<endl;

	std::auto_ptr<TestCls> auptr1(pTest);
	pTest = NULL;//交给auto_ptr了,就不需要自己在管理了,可以防止误删除

	cout<<"x:"<<auptr1->x<<endl;//可以直接调用参考类的共有方法或者变量。
	cout<<"x:"<<auptr1.get()->x<<endl;//可以通过get方法获取原指针。

	TestCls &testCls = *auptr1;
	testCls.x = 100;//可以通过*获取参考指针的引用。
	cout<<"x:"<<testCls.x<<endl;

	//可以通过release方法重新拿回指针,这样就需要自己管理
	pTest = auptr1.release();
	delete pTest;
	pTest = NULL;

	TestCls *pTestA = new TestCls("A");
	TestCls *pTestB = new TestCls("B");
	std::auto_ptr<TestCls> auptr2(pTestA);
	//调用reset,会先释放掉原有引用(pTestA),然后再持有新的引用(pTestB)
	auptr2.reset(pTestB);

	cout<<"leave testAutoPtrFunc\n";
}

输出:

enter testAutoPtrFunc
TestCls TEST Constructor Called
x:10
x:10
x:10
x:100
TestCls TEST Destructor Called
TestCls A Constructor Called
TestCls B Constructor Called
TestCls A Destructor Called
leave testAutoPtrFunc
TestCls B Destructor Called

参考网址【 http://www.cplusplus.com/reference/memory/auto_ptr/ 】

auto_ptr 和 auto_ptr_ref :

参考【 http://www.cnblogs.com/woud/archive/2013/05/15/3080644.html 】和【 http://jarfield.iteye.com/blog/746062 】,讲的非常透彻。

最后贴下源码:

template<class _Ty>
	struct auto_ptr_ref
		{	// proxy reference for auto_ptr copying
	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离开了作用域之后,就会调用析构函数,这里会delete掉管理的指针,也是
//auto_pter的核心所在
	~auto_ptr() _NOEXCEPT
		{	// 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());
		}
		
//get直接返回管理的指针
	_Ty *get() const _THROW0()
		{	// return wrapped pointer
		return (_Myptr);
		}

//release时会将管理的指针返回,然后将本地管理置NULL
	_Ty *release() _THROW0()
		{	// return wrapped pointer and give up ownership
		_Ty *_Tmp = _Myptr;
		_Myptr = 0;
		return (_Tmp);
		}

//reset时会先将已有的指针delete掉,然后再保存新的。这里新的可以为空,这样可以提前释放管理的指针
	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
	};

 

Leave a Reply

13 − 9 =

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据