赞
踩
- // 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);
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。