智能指針派生類—unique_ptr(STL源碼)


// unique_ptr指針(唯一指向資源的指針,每當賦值、構造時,轉讓右側指針數據到左側,右側爲空,即同一時間只有一個指針指向數據)
// 其中,千萬別在定義一個unique_ptr指針時出現下述情況已知unique_ptr<int> q(new int(1));q也可以是shared_ptr<int>類型
// unique_ptr<int> p(q.get());這是合法且編譯通過(但是就出現了兩智能指針指向同一內存的現象),所以當p離開其作用域且q依舊在其作用域範圍內時,p的釋放導致q爲懸空指針,q釋放時就會導致重複釋放而引起的錯誤。
// 例如:
std::unique_ptr<int> q(new int(111111));
//std::shared_ptr<int> qq = std::make_shared<int>(2222);
{
	//std::unique_ptr<int> p(q.get());		// 隱含錯誤:p和q同時指向同一內存,局部變量p離開作用於析構釋放內存,導致q成爲懸空指針
	//std::unique_ptr<int> pp(qq.get());	// 隱含錯誤:道理同上
	std::unique_ptr<int> p(q.release());	// .release().q主動放棄內存資源佔有權同時置空並返回原指針(ok),shared_ptr沒有釋放內存且返回原內存指針的函數
}
// TEMPLATE CLASS unique_ptr SCALAR
template<class _Ty,
	class _Dx>	// = default_delete<_Ty>
	class unique_ptr
		: private _Unique_ptr_base<_Ty, _Dx,
			is_empty<_Dx>::value	// 非空 或是 默認刪除器 則爲true(特化版)
				|| is_same<default_delete<_Ty>, _Dx>::value>
	{	// non-copyable pointer to an object
public:
	typedef unique_ptr<_Ty, _Dx> _Myt;	// 自身類型
	typedef _Unique_ptr_base<_Ty, _Dx,
		is_empty<_Dx>::value
			|| is_same<default_delete<_Ty>, _Dx>::value> _Mybase;// 基類類型
	typedef typename _Mybase::pointer pointer;
	typedef _Ty element_type;
	typedef _Dx deleter_type;

	using _Mybase::get_deleter;// 訪問申明

	unique_ptr() _NOEXCEPT
		: _Mybase(pointer())
		{	// default construct
		static_assert(!is_pointer<_Dx>::value,
			"unique_ptr constructed with null deleter pointer");
		}

	unique_ptr(nullptr_t) _NOEXCEPT
		: _Mybase(pointer())
		{	// null pointer construct
		static_assert(!is_pointer<_Dx>::value,
			"unique_ptr constructed with null deleter pointer");
		}
	// 不允許指針之間的賦值,但可以賦值爲0
	_Myt& operator=(nullptr_t) _NOEXCEPT
		{	// assign a null pointer
		reset();// 釋放資源
		return (*this);
		}

	explicit unique_ptr(pointer _Ptr) _NOEXCEPT
		: _Mybase(_Ptr)
		{	// construct with pointer
		static_assert(!is_pointer<_Dx>::value,
			"unique_ptr constructed with null deleter pointer");
		}

	unique_ptr(pointer _Ptr,
		typename _If<is_reference<_Dx>::value, _Dx,
			const typename remove_reference<_Dx>::type&>::type _Dt) _NOEXCEPT
		: _Mybase(_Ptr, _Dt)
		{	// construct with pointer and (maybe const) deleter&
		}

	unique_ptr(pointer _Ptr,
		typename remove_reference<_Dx>::type&& _Dt) _NOEXCEPT
		: _Mybase(_Ptr, _STD move(_Dt))
		{	// construct by moving deleter
		static_assert(!is_reference<_Dx>::value,
			"unique_ptr constructed with reference to rvalue deleter");
		}
	// 移動copy
	unique_ptr(unique_ptr&& _Right) _NOEXCEPT
		: _Mybase(_Right.release(),// 釋放右側無名對象
			_STD forward<_Dx>(_Right.get_deleter()))
		{	// construct by moving _Right
		}

	template<class _Ty2,
		class _Dx2,
		class = typename enable_if<!is_array<_Ty2>::value
			&& is_convertible<typename unique_ptr<_Ty2, _Dx2>::pointer,
				pointer>::value
			&& ((is_reference<_Dx>::value && is_same<_Dx, _Dx2>::value)
				|| (!is_reference<_Dx>::value
					&& is_convertible<_Dx2, _Dx>::value)),
			void>::type>
		unique_ptr(unique_ptr<_Ty2, _Dx2>&& _Right) _NOEXCEPT
			: _Mybase(_Right.release(),
				_STD forward<_Dx2>(_Right.get_deleter()))
		{	// construct by moving _Right
		}

	template<class _Ty2,
		class = typename enable_if<is_convertible<_Ty2 *, _Ty *>::value
			&& is_same<_Dx, default_delete<_Ty> >::value,
			void>::type>
		unique_ptr(auto_ptr<_Ty2>&& _Right) _NOEXCEPT
			: _Mybase(_Right.release())
		{	// construct by moving _Right
		}

	template<class _Ty2,
		class _Dx2>
		typename enable_if<!is_array<_Ty2>::value
			&& is_convertible<typename unique_ptr<_Ty2, _Dx2>::pointer,
				pointer>::value,
			_Myt&>::type
		operator=(unique_ptr<_Ty2, _Dx2>&& _Right) _NOEXCEPT
		{	// assign by moving _Right
		reset(_Right.release());
		this->get_deleter() = _STD forward<_Dx2>(_Right.get_deleter());
		return (*this);
		}
	// 移動賦值
	_Myt& operator=(_Myt&& _Right) _NOEXCEPT
		{	// assign by moving _Right
		if (this != &_Right)
			{	// different, do the move
			reset(_Right.release());
			this->get_deleter() = _STD forward<_Dx>(_Right.get_deleter());
			}
		return (*this);
		}

	void swap(_Myt& _Right) _NOEXCEPT
		{	// swap elements
		_Swap_adl(this->_Myptr, _Right._Myptr);
		_Swap_adl(this->get_deleter(),
			_Right.get_deleter());
		}

	~unique_ptr() _NOEXCEPT
		{	// destroy the object
		if (this->_Myptr != pointer())
			this->get_deleter()(this->_Myptr);// 析構,調用刪除器函數對象釋放資源
		}

	typename add_reference<_Ty>::type operator*() const
		{	// return reference to object
		return (*this->_Myptr);
		}

	pointer operator->() const _NOEXCEPT
		{	// return pointer to class object
		return (_STD pointer_traits<pointer>::pointer_to(**this));
		}

	pointer get() const _NOEXCEPT
		{	// return pointer to object
		return (this->_Myptr);
		}

	explicit operator bool() const _NOEXCEPT
		{	// test for non-null pointer
		return (this->_Myptr != pointer());
		}
	// 放棄對資源的控制,返回資源指針
	pointer release() _NOEXCEPT
		{	// yield ownership of pointer
		pointer _Ans = this->_Myptr;
		this->_Myptr = pointer();
		return (_Ans);
		}
	// 建立新的指針數據,釋放old指針數據
	void reset(pointer _Ptr = pointer()) _NOEXCEPT
		{	// establish new pointer
		pointer _Old = this->_Myptr;
		this->_Myptr = _Ptr;
		if (_Old != pointer())
			this->get_deleter()(_Old);
		}
	// 定義爲delete,不允許copy構造和賦值構造
	unique_ptr(const _Myt&) = delete;
	_Myt& operator=(const _Myt&) = delete;
	};







// TEMPLATE CLASS unique_ptr ARRAY
// 指針數組模板類
template<class _Ty,
	class _Dx>
	class unique_ptr<_Ty[], _Dx>
		: private _Unique_ptr_base<_Ty, _Dx,
			is_empty<_Dx>::value
				|| is_same<default_delete<_Ty[]>, _Dx>::value>
	{	// non-copyable pointer to an array object
public:
	typedef unique_ptr<_Ty[], _Dx> _Myt;
	typedef _Unique_ptr_base<_Ty, _Dx,
		is_empty<_Dx>::value
			|| is_same<default_delete<_Ty[]>, _Dx>::value> _Mybase;
	typedef typename _Mybase::pointer pointer;
	typedef _Ty element_type;
	typedef _Dx deleter_type;

	using _Mybase::get_deleter;

	unique_ptr() _NOEXCEPT
		: _Mybase(pointer())
		{	// default construct
		static_assert(!is_pointer<_Dx>::value,
			"unique_ptr constructed with null deleter pointer");
		}

	explicit unique_ptr(pointer _Ptr) _NOEXCEPT
		: _Mybase(_Ptr)
		{	// construct with pointer
		static_assert(!is_pointer<_Dx>::value,
			"unique_ptr constructed with null deleter pointer");
		}

	unique_ptr(pointer _Ptr,
		typename _If<is_reference<_Dx>::value, _Dx,
			const typename remove_reference<_Dx>::type&>::type _Dt) _NOEXCEPT
		: _Mybase(_Ptr, _Dt)
		{	// construct with pointer and (maybe const) deleter&
		}

	unique_ptr(pointer _Ptr,
		typename remove_reference<_Dx>::type&& _Dt) _NOEXCEPT
		: _Mybase(_Ptr, _STD move(_Dt))
		{	// construct by moving deleter
		static_assert(!is_reference<_Dx>::value,
			"unique_ptr constructed with reference to rvalue deleter");
		}

	unique_ptr(unique_ptr&& _Right) _NOEXCEPT
		: _Mybase(_Right.release(),
			_STD forward<_Dx>(_Right.get_deleter()))
		{	// construct by moving _Right
		}

	_Myt& operator=(_Myt&& _Right) _NOEXCEPT
		{	// assign by moving _Right
		if (this != &_Right)
			{	// different, do the swap
			reset(_Right.release());
			this->get_deleter() = _STD move(_Right.get_deleter());
			}
		return (*this);
		}

	unique_ptr(nullptr_t) _NOEXCEPT
		: _Mybase(pointer())
		{	// null pointer construct
		static_assert(!is_pointer<_Dx>::value,
			"unique_ptr constructed with null deleter pointer");
		}

	_Myt& operator=(nullptr_t) _NOEXCEPT
		{	// assign a null pointer
		reset();
		return (*this);
		}

	void reset(nullptr_t) _NOEXCEPT
		{	// establish new null pointer
		reset();
		}

	void swap(_Myt& _Right) _NOEXCEPT
		{	// swap elements
		_Swap_adl(this->_Myptr, _Right._Myptr);
		_Swap_adl(this->get_deleter(), _Right.get_deleter());
		}

	~unique_ptr() _NOEXCEPT
		{	// destroy the object
		_Delete();
		}

	// 重載[]
	typename add_reference<_Ty>::type operator[](size_t _Idx) const
		{	// return reference to object
		return (this->_Myptr[_Idx]);
		}

	pointer get() const _NOEXCEPT
		{	// return pointer to object
		return (this->_Myptr);
		}

	explicit operator bool() const _NOEXCEPT
		{	// test for non-null pointer
		return (this->_Myptr != pointer());
		}

	pointer release() _NOEXCEPT
		{	// yield ownership of pointer
		pointer _Ans = this->_Myptr;
		this->_Myptr = pointer();
		return (_Ans);
		}

	void reset(pointer _Ptr = pointer()) _NOEXCEPT
		{	// establish new pointer
		_Delete();
		this->_Myptr = _Ptr;
		}

	template<class _Ptr2>
		explicit unique_ptr(_Ptr2) = delete;

	template<class _Ptr2,
		class _Dx2>
		unique_ptr(_Ptr2, _Dx2) = delete;

	unique_ptr(const _Myt&) = delete;

	_Myt& operator=(const _Myt&) = delete;

	template<class _Ptr2>
		void reset(_Ptr2) = delete;

private:
	void _Delete()
		{	// delete the pointer
		if (this->_Myptr != pointer())
			this->get_deleter()(this->_Myptr);
		}
	};

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章