智能指针派生类—shared_ptr(STL源码)

// shared_ptr虽然能和其他shared_ptr共享同一内存,但是千万不能通过原始指针持有一个即将过期的指针,即2个非共享的share_ptr指向同一个对象,未增加引用计数导对象被析构两次情形如下:
std::shared_ptr<int> p= std::make_shared<int>(1);
{
	std::unique_ptr<int> q(new int(111111));// q也可以是shared_ptr
	p.reset(qw.get());// p会释放掉指向'std::make_shared<int>(1)'的内存,转而控制'new int(111111)'内存,但是却和q同时共享同一内存,但是q是临时变量,在{}执行完后释放内存,导致p成为悬空指针,后续在p析构时会重新再delete这块内存,导致重复释放出错
}
所以使用第三行reset语句的前提是你确保q放弃对其资源的控制,如q.release();
以上情形同时适用于unique_ptr
处于以上情况,c++11出了一种新特性为enable_shared_from_this类用于解决上述返回共同管理的指针的解决方案

// TEMPLATE CLASS shared_ptr
// shared_ptr智能指针类模板
template<class _Ty>
class shared_ptr
	: public _Ptr_base<_Ty>	// 继承自智能指针基类
{	// class for reference counted resource management    引用计数资源管理类
public:
	typedef shared_ptr<_Ty> _Myt;		// 定义自身 类型
	typedef _Ptr_base<_Ty> _Mybase;		// 定义基类 类型

//
// 构造函数
	shared_ptr() _NOEXCEPT
	{	// construct empty shared_ptr
	}
	// 允许从原始指针_Px显式构造
	template<class _Ux>
	explicit shared_ptr(_Ux *_Px)
	{	// construct shared_ptr object that owns _Px
		_Resetp(_Px);
	}
	// 参数2为 删除器类型(删除资源数据)
	template<class _Ux,
	class _Dx>
		shared_ptr(_Ux *_Px, _Dx _Dt)
	{	// construct with _Px, deleter
		_Resetp(_Px, _Dt);
	}

	shared_ptr(nullptr_t)
	{	// construct empty shared_ptr
	}

	template<class _Dx>
	shared_ptr(nullptr_t, _Dx _Dt)
	{	// construct with nullptr, deleter
		_Resetp((_Ty *)0, _Dt);
	}
	// 参数3:分配器类型(销毁计数器对象)
	template<class _Dx,
	class _Alloc>
		shared_ptr(nullptr_t, _Dx _Dt, _Alloc _Ax)
	{	// construct with nullptr, deleter, allocator
		_Resetp((_Ty *)0, _Dt, _Ax);
	}

	template<class _Ux,
	class _Dx,
	class _Alloc>
		shared_ptr(_Ux *_Px, _Dx _Dt, _Alloc _Ax)
	{	// construct with _Px, deleter, allocator
		_Resetp(_Px, _Dt, _Ax);
	}

// 从其他智能指针构造(调用基类的_Reset)
	template<class _Ty2>
	shared_ptr(const shared_ptr<_Ty2>& _Right, _Ty *_Px) _NOEXCEPT
	{	// construct shared_ptr object that aliases _Right
		this->_Reset(_Px, _Right);
	}
	// copy构造函数
		shared_ptr(const _Myt& _Other) _NOEXCEPT
	{	// construct shared_ptr object that owns same resource as _Other
		this->_Reset(_Other);
	}
	// enable_if的第一个参数(is_convertible<_Ty2 *, _Ty *>::value)为true时,才会内部定义type(第二个参数,这为void),否则无法通过编译
	// is_convertible<_Ty2 *, _Ty *>:判断是否可以被转化  第一个参数的类型 可以转化为第二个参数的类型
	// 例如对于类:如果A是基类,B是子类,那么B可以转化为A,也就是B是一种A;用is_convertible表示如下:
	// std::cout << std::boolalpha;   //输出格式调整,0为false,非0为true
	// std::is_convertible<B, A>::value << endl;// 判断B是否可以转化为A,并返回true or false
	template<class _Ty2,
	class = typename enable_if<is_convertible<_Ty2 *, _Ty *>::value,
		void>::type>
		shared_ptr(const shared_ptr<_Ty2>& _Other) _NOEXCEPT
	{	// construct shared_ptr object that owns same resource as _Other
		this->_Reset(_Other);
	}

		template<class _Ty2>
	explicit shared_ptr(const weak_ptr<_Ty2>& _Other,
		bool _Throw = true)
	{	// construct shared_ptr object that owns resource *_Other
		this->_Reset(_Other, _Throw);
	}

	// 从auto_ptr指针,移动构造函数
	template<class _Ty2>
	shared_ptr(auto_ptr<_Ty2>&& _Other)
	{	// construct shared_ptr object that owns *_Other.get()
		this->_Reset(_STD move(_Other));// move(左值)转为右值引用,调用基类void _Reset(auto_ptr<_Ty2>&& _Other)
	}
	// 类型转换
	template<class _Ty2>
	shared_ptr(const shared_ptr<_Ty2>& _Other, const _Static_tag& _Tag)
	{	// construct shared_ptr object for static_pointer_cast
		this->_Reset(_Other, _Tag);
	}

	template<class _Ty2>
	shared_ptr(const shared_ptr<_Ty2>& _Other, const _Const_tag& _Tag)
	{	// construct shared_ptr object for const_pointer_cast
		this->_Reset(_Other, _Tag);
	}

	template<class _Ty2>
	shared_ptr(const shared_ptr<_Ty2>& _Other, const _Dynamic_tag& _Tag)
	{	// construct shared_ptr object for dynamic_pointer_cast
		this->_Reset(_Other, _Tag);
	}
// 从shared_ptr指针,移动构造函数
	shared_ptr(_Myt&& _Right) _NOEXCEPT
		: _Mybase(_STD forward<_Myt>(_Right))// 转发右值引用属性(完全依照模板的参数的类型)
	{	// construct shared_ptr object that takes resource from _Right
	}

	template<class _Ty2,
	class = typename enable_if<is_convertible<_Ty2 *, _Ty *>::value,
		void>::type>
		shared_ptr(shared_ptr<_Ty2>&& _Right) _NOEXCEPT
		: _Mybase(_STD forward<shared_ptr<_Ty2> >(_Right))
	{	// construct shared_ptr object that takes resource from _Right
	}
// 从unique_ptr指针,移动构造函数
	template<class _Ux,
	class _Dx>
		shared_ptr(unique_ptr<_Ux, _Dx>&& _Right)
	{	// construct from unique_ptr
		_Resetp(_Right.release(), _Right.get_deleter());// 转移_Right的指针控制权给this,_Right为空
	}

//赋值移动构造函数
	template<class _Ux,
	class _Dx>
		_Myt& operator=(unique_ptr<_Ux, _Dx>&& _Right)
	{	// move from unique_ptr
		shared_ptr(_STD move(_Right)).swap(*this);
		return (*this);
	}

	_Myt& operator=(_Myt&& _Right) _NOEXCEPT
	{	// construct shared_ptr object that takes resource from _Right
		shared_ptr(_STD move(_Right)).swap(*this);
		return (*this);
	}

		template<class _Ty2>
	_Myt& operator=(shared_ptr<_Ty2>&& _Right) _NOEXCEPT
	{	// construct shared_ptr object that takes resource from _Right
		shared_ptr(_STD move(_Right)).swap(*this);
		return (*this);
	}
// 析构,引用计数-1
		~shared_ptr() _NOEXCEPT
	{	// release resource
		this->_Decref();
	}

//赋值copy构造函数
		_Myt& operator=(const _Myt& _Right) _NOEXCEPT
	{	// assign shared ownership of resource owned by _Right
		shared_ptr(_Right).swap(*this);// shared_ptr(_Right)临时对象先递增右值的引用计数,swap交换后临时对象指向左值,即this指向了引用计数已经增1后的右值(即_Right)了,左值从之前的this指向它,编程临时对象指向它,所以到这一步时,之前左值的计数不变,等到{}代码结束后,临时对象释放,调用析构,引用计数-1,所以从代码层面印证了 =右边计数+1,左边计数-1
		return (*this);
	}

		template<class _Ty2>
	_Myt& operator=(const shared_ptr<_Ty2>& _Right) _NOEXCEPT
	{	// assign shared ownership of resource owned by _Right
		shared_ptr(_Right).swap(*this);
		return (*this);
	}

		template<class _Ty2>
	_Myt& operator=(auto_ptr<_Ty2>&& _Right)
	{	// assign ownership of resource pointed to by _Right
		shared_ptr(_STD move(_Right)).swap(*this);
		return (*this);
	}

// 释放资源,或重新指向_Px
	// 释放资源并转换为空的shared_ptr对象
	void reset() _NOEXCEPT
	{	// release resource and convert to empty shared_ptr object
		shared_ptr().swap(*this);// 临时无名对象 和 当前对象 交换,然后无名对象在函数执行完后析构,释放资源
	}

		template<class _Ux>
	void reset(_Ux *_Px)
	{	// release, take ownership of _Px
		shared_ptr(_Px).swap(*this);
	}

	template<class _Ux,
	class _Dx>
		void reset(_Ux *_Px, _Dx _Dt)
	{	// release, take ownership of _Px, with deleter _Dt
		shared_ptr(_Px, _Dt).swap(*this);
	}

	template<class _Ux,
	class _Dx,
	class _Alloc>
		void reset(_Ux *_Px, _Dx _Dt, _Alloc _Ax)
	{	// release, take ownership of _Px, with deleter _Dt, allocator _Ax
		shared_ptr(_Px, _Dt, _Ax).swap(*this);
	}

	void swap(_Myt& _Other) _NOEXCEPT
	{	// swap pointers
		this->_Swap(_Other);
	}

	// 得到原始数据指针
		_Ty *get() const _NOEXCEPT
	{	// return pointer to resource
		return (this->_Get());
	}
	// 数据的引用(重载解地址运算符*)
		typename add_reference<_Ty>::type operator*() const _NOEXCEPT
	{	// return reference to resource
		return (*this->_Get());
	}
	// 得到原始数据指针(重载指针访问运算符->)
		_Ty *operator->() const _NOEXCEPT
	{	// return pointer to resource
		return (this->_Get());
	}
	// 是否计数为1
		bool unique() const _NOEXCEPT
	{	// return true if no other shared_ptr object owns this resource
		return (this->use_count() == 1);
	}
	// 本类型到bool的转换,不允许使用参数,即if(!shared_ptr)时调用
		explicit operator bool() const _NOEXCEPT
	{	// test if shared_ptr object owns no resource
		return (this->_Get() != 0);
	}

private:
	// 内部构造时调用_Resetp
	template<class _Ux>
	void _Resetp(_Ux *_Px)
	{	// release, take ownership of _Px
		_TRY_BEGIN	// allocate control block and reset
			_Resetp0(_Px, new _Ref_count<_Ux>(_Px));
		_CATCH_ALL	// allocation failed, delete resource
			delete _Px;
		_RERAISE;
		_CATCH_END
	}

	template<class _Ux,
	class _Dx>
		void _Resetp(_Ux *_Px, _Dx _Dt)
	{	// release, take ownership of _Px, deleter _Dt
		_TRY_BEGIN	// allocate control block and reset
			_Resetp0(_Px, new _Ref_count_del<_Ux, _Dx>(_Px, _Dt));// 资源_Px同时交给两方管理,一处为智能指针的基类(_Ref_count_del)的成员_Ty *_Ptr;另一处为成员_Ref_count_base *_Rep(本身为计数基类)的派生类对象(这里为_Ref_count_del)的新成员_Ty * _Ptr;
		_CATCH_ALL	// allocation failed, delete resource
			_Dt(_Px);
		_RERAISE;
		_CATCH_END
	}

	template<class _Ux,
	class _Dx,
	class _Alloc>
		void _Resetp(_Ux *_Px, _Dx _Dt, _Alloc _Ax)
	{	// release, take ownership of _Px, deleter _Dt, allocator _Ax
		typedef _Ref_count_del_alloc<_Ux, _Dx, _Alloc> _Refd;
		typename _Alloc::template rebind<_Refd>::other _Al = _Ax;

		_TRY_BEGIN	// allocate control block and reset
			_Refd *_Ptr = _Al.allocate(1);
		::new (_Ptr)_Refd(_Px, _Dt, _Al);
		_Resetp0(_Px, _Ptr);
		_CATCH_ALL	// allocation failed, delete resource
			_Dt(_Px);
		_RERAISE;
		_CATCH_END
	}

public:
	template<class _Ux>
	void _Resetp0(_Ux *_Px, _Ref_count_base *_Rx)
	{	// release resource and take ownership of _Px
		this->_Reset0(_Px, _Rx);
		_Enable_shared(_Px, _Rx);    // 管理指向同一内存的指针,管理的类需继承enable_shared_from_this
	}
};

// _Resetp0(_Px, new _Ref_count_del<_Ux, _Dx>(_Px, _Dt));
// 由此可见,资源由子对象_Ref_count_base的派生类对象指针_Rep管理,
// 1.当智能指针.reset()时,当前指针(含资源,引用计数n)与临时无名对象指针(没有资源,引用计数0)交换,临时无名对象(此时有资源且引用计数为n)在函数执行完后会析构;减少引用计数,
// 2.当多个指向a同一引用的智能指针放弃自己的控制权时(如.reset()或 = otherPtr时,指向a的引用计数减少)
// 上述两种情况 当引用计数减少,直至0时,_Rep(派生类)会调用自己的纯虚函数_Destroy();_Decwref();从而释放资源




/非成员函数,重载操作符,用于两智能指针间的比较(只列举几个)/
// 重载==,判断两个智能指针是否管理同一个资源
template<class _Ty1,
class _Ty2>
	bool operator==(const shared_ptr<_Ty1>& _Left,
	const shared_ptr<_Ty2>& _Right) _NOEXCEPT
{	// test if shared_ptr == shared_ptr
	return (_Left.get() == _Right.get());
}
// 重载!=,判断两个智能指针是否管理不同一个资源
template<class _Ty1,
class _Ty2>
	bool operator!=(const shared_ptr<_Ty1>& _Left,
	const shared_ptr<_Ty2>& _Right) _NOEXCEPT
{	// test if shared_ptr != shared_ptr
	return (!(_Left == _Right));// 调用operator==
}
// 重载<,判断参数1智能指针管理的资源地址是否小于参数2的
template<class _Ty1,
class _Ty2>
	bool operator<(const shared_ptr<_Ty1>& _Left,
	const shared_ptr<_Ty2>& _Right) _NOEXCEPT
{	// test if shared_ptr < shared_ptr
	return (less<decltype(_Always_false<_Ty1>::value// less的模板参数为_Right.get()的类型,因为_Always_false<_Ty1>::value为false
	? _Left.get() : _Right.get())>()(
	_Left.get(), _Right.get()));
}
// 重载>=,判断参数1智能指针管理的资源地址是否不小于参数2的
template<class _Ty1,
class _Ty2>
	bool operator>=(const shared_ptr<_Ty1>& _Left,
	const shared_ptr<_Ty2>& _Right) _NOEXCEPT
{	// shared_ptr >= shared_ptr
	return (!(_Left < _Right));
}
// 其余比较函数类似
// 上述比较函数为普通非成员模板函数,但是因为是两指针之间的比较,可以在类内实现,成为单参数的成员函数(p1 < p2,即调用p1.operator<(p2));


/非成员函数,重载操作符,用于智能指针和空指针间的比较(只列举几个)/
// 重载==,判断_Left智能指针管理的资源地址是否为0(没管理任何内存),if(_Left == 0)时调用,==后必须0,非0报编译错误
template<class _Ty>
bool operator==(const shared_ptr<_Ty>& _Left,
	nullptr_t) _NOEXCEPT
{	// test if shared_ptr == nullptr
	return (_Left.get() == (_Ty *)0);
}
// 重载==,和上述区别为if(0 == _Left)时调用,==前必须0,非0报编译错误
template<class _Ty>
bool operator==(nullptr_t,
	const shared_ptr<_Ty>& _Right) _NOEXCEPT
{	// test if nullptr == shared_ptr
	return ((_Ty *)0 == _Right.get());
}
// 必须和0(nullptr_t)比较,包括其他未举的例子
// 当参数为nullptr_t时,就不能写成成员模板函数了,只能写成普通模板函数,因为对于每个操作符都有两个重载函数,例如上述
// 对于==操作符的重载有两个(参数1,2互换位置),之所以这个写,是因为当有语句if(p == 0)或if (0 == p)是,都能正常调用上述两个函数。
// 而写成成员函数时,if(p == 0)可以正常调用bool operator==(nullptr_t),被解释为p.operator==(0),但是当if(0 == p ),解释为0.operator==(p)显然是不对的。




// TEMPLATE FUNCTION make_shared
template<class _Ty,class... _Types> 
inline shared_ptr<_Ty> make_shared(_Types&&... _Args)
{	// make a shared_ptr
	_Ref_count_obj<_Ty> *_Rx = new _Ref_count_obj<_Ty>(_STD forward<_Types>(_Args)...);

	shared_ptr<_Ty> _Ret;
	_Ret._Resetp0(_Rx->_Getptr(), _Rx);
	return (_Ret);
}
// std::shared_ptr<int> p = std::make_shared<int>(1);

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值